Viele in JavaScript integrierte Funktionen unterstützen eine beliebige Anzahl von Argumenten.
Zum Beispiel:
Math.max(arg1, arg2, ..., argN)
– gibt das größte der Argumente zurück.
Object.assign(dest, src1, ..., srcN)
– kopiert Eigenschaften von src1..N
nach dest
.
…und so weiter.
In diesem Kapitel erfahren Sie, wie Sie dasselbe tun. Und auch, wie man Arrays als Parameter an solche Funktionen übergibt.
...
Eine Funktion kann unabhängig von ihrer Definition mit beliebig vielen Argumenten aufgerufen werden.
Wie hier:
Funktion sum(a, b) { gib a + b zurück; } alarm( sum(1, 2, 3, 4, 5) );
Es wird kein Fehler aufgrund „übermäßiger“ Argumente auftreten. Aber natürlich werden im Ergebnis nur die ersten beiden gezählt, daher ist das Ergebnis im obigen Code 3
.
Die restlichen Parameter können in die Funktionsdefinition einbezogen werden, indem drei Punkte ...
gefolgt vom Namen des Arrays verwendet werden, das sie enthalten soll. Die Punkte bedeuten wörtlich „die restlichen Parameter in einem Array zusammenfassen“.
Um beispielsweise alle Argumente im Array args
zusammenzufassen:
function sumAll(...args) { // args ist der Name für das Array sei Summe = 0; for (let arg of args) sum += arg; Rückgabesumme; } alarm( sumAll(1) ); // 1 alarm( sumAll(1, 2) ); // 3 alarm( sumAll(1, 2, 3) ); // 6
Wir können uns dafür entscheiden, die ersten Parameter als Variablen zu erhalten und nur den Rest zu sammeln.
Hier gehen die ersten beiden Argumente in Variablen und der Rest in titles
Array ein:
Funktion showName(firstName, lastName, ...titles) { alarm( Vorname + ' ' + Nachname ); // Julius Cäsar // der Rest kommt in das Titles-Array // dh titles = ["Konsul", "Imperator"] alarm( titles[0] ); // Konsul Alert( Titel[1] ); // Imperator alarm( titles.length ); // 2 } showName("Julius", "Caesar", "Konsul", "Imperator");
Die restlichen Parameter müssen am Ende stehen
Die restlichen Parameter erfassen alle verbleibenden Argumente, sodass Folgendes keinen Sinn ergibt und einen Fehler verursacht:
function f(arg1, ...rest, arg2) { // arg2 nach ...rest ?! // Fehler }
Der ...rest
muss immer der letzte sein.
Es gibt auch ein spezielles Array-ähnliches Objekt namens arguments
, das alle Argumente nach ihrem Index enthält.
Zum Beispiel:
Funktion showName() { alarm( arguments.length ); alarm( argumente[0] ); alarm( argumente[1] ); // es ist iterierbar // for(arg der Argumente lassen) alarm(arg); } // zeigt: 2, Julius, Caesar showName("Julius", "Caesar"); // zeigt: 1, Ilya, undefiniert (kein zweites Argument) showName("Ilya");
Früher gab es in der Sprache keine Restparameter und die Verwendung arguments
war die einzige Möglichkeit, alle Argumente der Funktion abzurufen. Und es funktioniert immer noch, wir können es im alten Code finden.
Der Nachteil ist jedoch, dass arguments
zwar sowohl arrayartig als auch iterierbar ist, aber kein Array ist. Es unterstützt keine Array-Methoden, daher können wir beispielsweise nicht arguments.map(...)
aufrufen.
Außerdem enthält es immer alle Argumente. Wir können sie nicht teilweise erfassen, wie wir es mit den Restparametern getan haben.
Wenn wir diese Funktionen benötigen, werden Ruheparameter bevorzugt.
Pfeilfunktionen haben keine "arguments"
Wenn wir über eine Pfeilfunktion auf das arguments
zugreifen, werden diese von der äußeren „normalen“ Funktion übernommen.
Hier ist ein Beispiel:
Funktion f() { let showArg = () => alarm(arguments[0]); showArg(); } f(1); // 1
Wie wir uns erinnern, haben Pfeilfunktionen kein eigenes this
. Jetzt wissen wir, dass sie auch nicht über das Objekt arguments
verfügen.
Wir haben gerade gesehen, wie man aus der Liste der Parameter ein Array erhält.
Aber manchmal müssen wir genau das Gegenteil tun.
Es gibt beispielsweise eine integrierte Funktion Math.max, die die größte Zahl aus einer Liste zurückgibt:
alarm( Math.max(3, 5, 1) ); // 5
Nehmen wir nun an, wir haben ein Array [3, 5, 1]
. Wie rufen wir damit Math.max
auf?
Es „wie es ist“ zu übergeben, wird nicht funktionieren, da Math.max
eine Liste numerischer Argumente und kein einzelnes Array erwartet:
sei arr = [3, 5, 1]; alarm( Math.max(arr) ); // NaN
Und sicherlich können wir Elemente im Code Math.max(arr[0], arr[1], arr[2])
nicht manuell auflisten, da wir möglicherweise nicht sicher sind, wie viele es sind. Während unser Skript ausgeführt wird, kann es viele oder gar keine geben. Und das würde hässlich werden.
Verbreiten Sie die Syntax zur Rettung! Es sieht ähnlich aus wie Rest-Parameter, die ebenfalls ...
verwenden, macht aber genau das Gegenteil.
Wenn ...arr
im Funktionsaufruf verwendet wird, „erweitert“ es ein iterierbares Objekt arr
in die Liste der Argumente.
Für Math.max
:
sei arr = [3, 5, 1]; alarm( Math.max(...arr) ); // 5 (Spread verwandelt Array in eine Liste von Argumenten)
Wir können auch mehrere Iterables auf diese Weise übergeben:
sei arr1 = [1, -2, 3, 4]; sei arr2 = [8, 3, -8, 1]; alarm( Math.max(...arr1, ...arr2) ); // 8
Wir können die Spread-Syntax sogar mit normalen Werten kombinieren:
sei arr1 = [1, -2, 3, 4]; sei arr2 = [8, 3, -8, 1]; alarm( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
Außerdem kann die Spread-Syntax zum Zusammenführen von Arrays verwendet werden:
sei arr = [3, 5, 1]; sei arr2 = [8, 9, 15]; let merged = [0, ...arr, 2, ...arr2]; Warnung (zusammengeführt); // 0,3,5,1,2,8,9,15 (0, dann arr, dann 2, dann arr2)
In den obigen Beispielen haben wir ein Array verwendet, um die Spread-Syntax zu demonstrieren, aber jedes iterierbare Array reicht aus.
Hier verwenden wir beispielsweise die Spread-Syntax, um die Zeichenfolge in ein Zeichenarray umzuwandeln:
let str = "Hallo"; alarm( [...str] ); // Hallo
Die Spread-Syntax verwendet intern Iteratoren, um Elemente zu sammeln, genau wie dies bei for..of
der Fall ist.
Für eine Zeichenfolge gibt for..of
also Zeichen zurück und ...str
wird zu "H","e","l","l","o"
. Die Liste der Zeichen wird an den Array-Initialisierer [...str]
übergeben.
Für diese spezielle Aufgabe könnten wir auch Array.from
verwenden, da es ein Iterable (wie einen String) in ein Array konvertiert:
let str = "Hallo"; // Array.from konvertiert ein Iterable in ein Array alarm( Array.from(str) ); // Hallo
Das Ergebnis ist das gleiche wie [...str]
.
Aber es gibt einen subtilen Unterschied zwischen Array.from(obj)
und [...obj]
:
Array.from
arbeitet sowohl mit Array-ähnlichen als auch mit iterierbaren Elementen.
Die Spread-Syntax funktioniert nur mit Iterables.
Für die Aufgabe, etwas in ein Array umzuwandeln, ist Array.from
tendenziell universeller.
Erinnern Sie sich, als wir in der Vergangenheit über Object.assign()
gesprochen haben?
Das Gleiche ist mit der Spread-Syntax möglich.
sei arr = [1, 2, 3]; let arrCopy = [...arr]; // Verteilen Sie das Array in eine Liste von Parametern // dann das Ergebnis in ein neues Array einfügen // Haben die Arrays den gleichen Inhalt? Alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // WAHR // sind die Arrays gleich? alarm(arr === arrCopy); // false (nicht dieselbe Referenz) // Durch das Ändern unseres anfänglichen Arrays wird die Kopie nicht geändert: arr.push(4); alarm(arr); // 1, 2, 3, 4 alarm(arrCopy); // 1, 2, 3
Beachten Sie, dass Sie auf die gleiche Weise eine Kopie eines Objekts erstellen können:
sei obj = { a: 1, b: 2, c: 3 }; let objCopy = { ...obj }; // Verteile das Objekt in eine Liste von Parametern // dann das Ergebnis in einem neuen Objekt zurückgeben // Haben die Objekte den gleichen Inhalt? Alert(JSON.stringify(obj) === JSON.stringify(objCopy)); // WAHR // sind die Objekte gleich? alarm(obj === objCopy); // false (nicht dieselbe Referenz) // Durch das Ändern unseres ursprünglichen Objekts wird die Kopie nicht geändert: obj.d = 4; alarm(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4} alarm(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3}
Diese Art des Kopierens eines Objekts ist viel kürzer als let objCopy = Object.assign({}, obj)
oder für ein Array let arrCopy = Object.assign([], arr)
daher verwenden wir sie lieber, wann immer wir können.
Wenn wir im Code "..."
sehen, handelt es sich entweder um Restparameter oder um die Spread-Syntax.
Es gibt eine einfache Möglichkeit, zwischen ihnen zu unterscheiden:
Wenn ...
am Ende der Funktionsparameter steht, handelt es sich um „Restparameter“ und sammelt den Rest der Argumentliste in einem Array.
Wenn ...
in einem Funktionsaufruf oder ähnlichem vorkommt, spricht man von einer „Spread-Syntax“ und erweitert ein Array in eine Liste.
Verwenden Sie Muster:
Restparameter werden verwendet, um Funktionen zu erstellen, die eine beliebige Anzahl von Argumenten akzeptieren.
Die Spread-Syntax wird verwendet, um ein Array an Funktionen zu übergeben, die normalerweise eine Liste mit vielen Argumenten erfordern.
Zusammen helfen sie dabei, problemlos zwischen einer Liste und einer Reihe von Parametern zu wechseln.
Alle Argumente eines Funktionsaufrufs sind auch in „alten“ arguments
verfügbar: Array-ähnliches iterierbares Objekt.