Das Überladen von Argumenten in Javascript hat mehrere Aspekte:
Variable Argumente - Sie können verschiedene Sätze von Argumenten (sowohl in Typ als auch in Menge) übergeben, und die Funktion verhält sich so, dass sie mit den an sie übergebenen Argumenten übereinstimmt.
Standardargumente - Sie können einen Standardwert für ein Argument definieren, wenn es nicht übergeben wird.
Benannte Argumente - Die Reihenfolge der Argumente spielt keine Rolle mehr und Sie benennen nur, welche Argumente Sie an die Funktion übergeben möchten.
Unten finden Sie einen Abschnitt zu jeder dieser Kategorien der Argumentbehandlung.
Variable Argumente
Da in Javascript keine Typprüfung für Argumente oder die erforderliche Anzahl von Argumenten vorhanden ist, können Sie nur eine Implementierung verwenden myFunc(), die sich an die an sie übergebenen Argumente anpassen kann, indem Sie den Typ, das Vorhandensein oder die Anzahl der Argumente überprüfen.
jQuery macht das die ganze Zeit. Sie können einige der Argumente optional machen oder in Ihrer Funktion verzweigen, je nachdem, welche Argumente an sie übergeben werden.
Bei der Implementierung dieser Arten von Überlastungen stehen Ihnen verschiedene Techniken zur Verfügung:
- Sie können das Vorhandensein eines bestimmten Arguments überprüfen, indem Sie überprüfen, ob der deklarierte Argumentname Wert ist
undefined.
- Sie können die Gesamtmenge oder Argumente mit überprüfen
arguments.length.
- Sie können den Typ eines bestimmten Arguments überprüfen.
- Für eine variable Anzahl von Argumenten können Sie das
argumentsPseudo-Array verwenden, um auf ein bestimmtes Argument mit zuzugreifen arguments[i].
Hier sind einige Beispiele:
Schauen wir uns die obj.data()Methode von jQuery an . Es werden vier verschiedene Nutzungsformen unterstützt:
obj.data("key");
obj.data("key", value);
obj.data();
obj.data(object);
Jeder löst ein anderes Verhalten aus und würde ohne diese dynamische Form der Überladung vier separate Funktionen erfordern.
So kann man zwischen all diesen Optionen auf Englisch unterscheiden und sie dann alle im Code kombinieren:
// get the data element associated with a particular key value
obj.data("key");
Wenn das erste übergebene Argument .data()eine Zeichenfolge ist und das zweite Argument undefined, muss der Aufrufer dieses Formular verwenden.
// set the value associated with a particular key
obj.data("key", value);
Wenn das zweite Argument nicht undefiniert ist, legen Sie den Wert eines bestimmten Schlüssels fest.
// get all keys/values
obj.data();
Wenn keine Argumente übergeben werden, geben Sie alle Schlüssel / Werte in einem zurückgegebenen Objekt zurück.
// set all keys/values from the passed in object
obj.data(object);
Wenn der Typ des ersten Arguments ein einfaches Objekt ist, legen Sie alle Schlüssel / Werte von diesem Objekt fest.
So können Sie all diese Elemente in einem Satz Javascript-Logik kombinieren:
// method declaration for .data()
data: function(key, value) {
if (arguments.length === 0) {
// .data()
// no args passed, return all keys/values in an object
} else if (typeof key === "string") {
// first arg is a string, look at type of second arg
if (typeof value !== "undefined") {
// .data("key", value)
// set the value for a particular key
} else {
// .data("key")
// retrieve a value for a key
}
} else if (typeof key === "object") {
// .data(object)
// set all key/value pairs from this object
} else {
// unsupported arguments passed
}
},
Der Schlüssel zu dieser Technik besteht darin, sicherzustellen, dass alle Arten von Argumenten, die Sie akzeptieren möchten, eindeutig identifizierbar sind und es keine Verwirrung darüber gibt, welche Form der Anrufer verwendet. Dies erfordert im Allgemeinen die richtige Reihenfolge der Argumente und die Sicherstellung, dass Typ und Position der Argumente so eindeutig sind, dass Sie immer erkennen können, welches Formular verwendet wird.
Wenn Sie beispielsweise eine Funktion haben, die drei Zeichenfolgenargumente akzeptiert:
obj.query("firstArg", "secondArg", "thirdArg");
Sie können das dritte Argument leicht optional machen und diese Bedingung leicht erkennen, aber Sie können nicht nur das zweite Argument optional machen, da Sie nicht sagen können, welches dieser Argumente der Anrufer übergeben soll, da es keine Möglichkeit gibt, festzustellen, ob das zweite Argument vorliegt Das Argument soll das zweite Argument sein, oder das zweite Argument wurde weggelassen. Was also an der Stelle des zweiten Arguments steht, ist tatsächlich das dritte Argument:
obj.query("firstArg", "secondArg");
obj.query("firstArg", "thirdArg");
Da alle drei Argumente vom gleichen Typ sind, können Sie den Unterschied zwischen verschiedenen Argumenten nicht erkennen, sodass Sie nicht wissen, was der Aufrufer beabsichtigt hat. Bei diesem Aufrufstil kann nur das dritte Argument optional sein. Wenn Sie das zweite Argument weglassen möchten, muss es stattdessen als null(oder ein anderer erkennbarer Wert) übergeben werden, und Ihr Code erkennt Folgendes:
obj.query("firstArg", null, "thirdArg");
Hier ist ein jQuery-Beispiel für optionale Argumente. Beide Argumente sind optional und nehmen Standardwerte an, wenn sie nicht übergeben werden:
clone: function( dataAndEvents, deepDataAndEvents ) {
dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
return this.map( function () {
return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
});
},
Hier ist ein jQuery-Beispiel, bei dem das Argument fehlen kann oder einer von drei verschiedenen Typen, wodurch Sie vier verschiedene Überladungen erhalten:
html: function( value ) {
if ( value === undefined ) {
return this[0] && this[0].nodeType === 1 ?
this[0].innerHTML.replace(rinlinejQuery, "") :
null;
// See if we can take a shortcut and just use innerHTML
} else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
value = value.replace(rxhtmlTag, "<$1></$2>");
try {
for ( var i = 0, l = this.length; i < l; i++ ) {
// Remove element nodes and prevent memory leaks
if ( this[i].nodeType === 1 ) {
jQuery.cleanData( this[i].getElementsByTagName("*") );
this[i].innerHTML = value;
}
}
// If using innerHTML throws an exception, use the fallback method
} catch(e) {
this.empty().append( value );
}
} else if ( jQuery.isFunction( value ) ) {
this.each(function(i){
var self = jQuery( this );
self.html( value.call(this, i, self.html()) );
});
} else {
this.empty().append( value );
}
return this;
},
Benannte Argumente
In anderen Sprachen (wie Python) können benannte Argumente übergeben werden, um nur einige Argumente zu übergeben und die Argumente unabhängig von der Reihenfolge zu machen, in der sie übergeben werden. Javascript unterstützt die Funktion benannter Argumente nicht direkt. Ein Entwurfsmuster, das üblicherweise an seiner Stelle verwendet wird, besteht darin, eine Karte mit Eigenschaften / Werten zu übergeben. Dies kann durch Übergeben eines Objekts mit Eigenschaften und Werten erfolgen. In ES6 und höher können Sie tatsächlich ein Map-Objekt selbst übergeben.
Hier ist ein einfaches ES5-Beispiel:
jQuery's $.ajax() akzeptiert eine Verwendungsform, bei der Sie nur einen einzelnen Parameter übergeben, bei dem es sich um ein reguläres Javascript-Objekt mit Eigenschaften und Werten handelt. Welche Eigenschaften Sie übergeben, bestimmt, welche Argumente / Optionen an den Ajax-Aufruf übergeben werden. Einige können erforderlich sein, viele sind optional. Da es sich um Eigenschaften eines Objekts handelt, gibt es keine bestimmte Reihenfolge. Tatsächlich gibt es mehr als 30 verschiedene Eigenschaften, die an dieses Objekt übergeben werden können. Es ist nur eine (die URL) erforderlich.
Hier ist ein Beispiel:
$.ajax({url: "http://www.example.com/somepath", data: myArgs, dataType: "json"}).then(function(result) {
// process result here
});
Innerhalb der $.ajax()Implementierung kann es dann einfach abfragen, welche Eigenschaften an das eingehende Objekt übergeben wurden, und diese als benannte Argumente verwenden. Dies kann entweder mit for (prop in obj)oder durch Abrufen aller Eigenschaften in einem Array mit Object.keys(obj)und anschließendes Iterieren dieses Arrays erfolgen.
Diese Technik wird in Javascript sehr häufig verwendet, wenn eine große Anzahl von Argumenten vorhanden ist und / oder viele Argumente optional sind. Hinweis: Dies stellt eine Belastung für die Implementierungsfunktion dar, um sicherzustellen, dass ein minimal gültiger Satz von Argumenten vorhanden ist, und um dem Aufrufer ein Debug-Feedback zu geben, was fehlt, wenn nicht genügend Argumente übergeben werden (wahrscheinlich durch Auslösen einer Ausnahme mit einer hilfreichen Fehlermeldung). .
In einer ES6-Umgebung ist es möglich, mithilfe der Destrukturierung Standardeigenschaften / -werte für das oben übergebene Objekt zu erstellen. Dies wird in diesem Referenzartikel ausführlicher erläutert .
Hier ist ein Beispiel aus diesem Artikel:
function selectEntries({ start=0, end=-1, step=1 } = {}) {
···
};
Dies schafft Standardeigenschaften und Werte für die start, endund stepEigenschaften auf ein Objekt auf den übergebenenselectEntries() Funktion.
Standardwerte für Funktionsargumente
In ES6 fügt Javascript eine integrierte Sprachunterstützung für Standardwerte für Argumente hinzu.
Beispielsweise:
function multiply(a, b = 1) {
return a*b;
}
multiply(5); // 5
Weitere Beschreibung der Möglichkeiten, wie dies hier auf MDN verwendet werden kann .