Ich habe in letzter Zeit mehr recherchiert, was es Neues in JavaScript gibt, und mich über viele der neuen Funktionen und Syntaxverbesserungen auf dem Laufenden gehalten, die in ES6 (d. h. ES2015 und später) enthalten sind.
Sie haben wahrscheinlich von den üblichen Dingen gehört und begonnen, sie zu verwenden: Pfeilfunktionen, let und const, Rest- und Spread-Operatoren usw. Eine Funktion, die meine Aufmerksamkeit erregt hat, ist die Verwendung von Standardparametern in Funktionen, die jetzt ein offizielles ES6+-Feature ist. Dies ist die Fähigkeit, dass Ihre Funktionen Parameter mit Standardwerten initialisieren, auch wenn der Funktionsaufruf diese nicht enthält.
Das Feature selbst ist in seiner einfachsten Form ziemlich einfach, aber es gibt einige Feinheiten und Fallstricke, die Sie beachten möchten, die ich in diesem Beitrag mit einigen Codebeispielen und Demos klarstellen werde.
Standardparameter in ES5 und früher
Eine Funktion, die für nicht deklarierte Parameter automatisch Standardwerte liefert, kann eine vorteilhafte Absicherung für Ihre Programme sein, und dies ist nichts Neues.
Vor ES6 haben Sie möglicherweise ein Muster wie dieses gesehen oder verwendet
function getInfo (name, year, color) {
year = (typeof year !== 'undefined') ? year : 2018;
color = (typeof color !== 'undefined') ? color : 'Blue';
// remainder of the function...
}
In diesem Fall hat die Funktion getInfo() nur einen obligatorischen Parameter: name. Die Parameter year und color sind optional, sodass sie Standardwerte erhalten, wenn sie bei einem Aufruf von getInfo() nicht als Argumente angegeben werden.
getInfo('Chevy', 1957, 'Green');
getInfo('Benz', 1965); // default for color is "Blue"
getInfo('Honda'); // defaults are 2018 and "Blue"
Probieren Sie es auf CodePen aus
Ohne diese Art von Prüfung und Absicherung würden nicht initialisierte Parameter standardmäßig den Wert undefined erhalten, was normalerweise nicht erwünscht ist.
Sie könnten auch ein Truthy/Falsy-Muster verwenden, um nach Parametern zu suchen, die keine Werte haben
function getInfo (name, year, color) {
year = year || 2018;
color = color || 'Blue';
// remainder of the function...
}
Aber dies kann in einigen Fällen Probleme verursachen. Im obigen Beispiel, wenn Sie 0 für das Jahr übergeben, überschreibt der Standardwert 2018 diesen, da 0 als falsy ausgewertet wird. In diesem speziellen Beispiel ist es unwahrscheinlich, dass Sie sich darum kümmern würden, aber es gibt viele Fälle, in denen Ihre App einen Wert von 0 als gültige Zahl anstelle eines falsy-Werts akzeptieren möchte.
Probieren Sie es auf CodePen aus
Natürlich müssen Sie selbst mit dem typeof-Muster möglicherweise weitere Prüfungen durchführen, um eine wirklich schusssichere Lösung zu erhalten. Zum Beispiel erwarten Sie möglicherweise eine optionale Callback-Funktion als Parameter. In diesem Fall würde eine Prüfung nur gegen undefined nicht ausreichen. Sie müssten auch prüfen, ob der übergebene Wert eine gültige Funktion ist.
Das war also eine kurze Zusammenfassung, wie wir Standardparameter vor ES6 gehandhabt haben. Schauen wir uns eine viel bessere Methode an.
Standardparameter in ES6
Wenn Ihre App aus Legacy-Gründen oder wegen Browserunterstützung die Verwendung von Pre-ES6-Features erfordert, müssen Sie möglicherweise etwas Ähnliches wie oben beschrieben tun. Aber ES6 hat dies viel einfacher gemacht. Hier erfahren Sie, wie Sie Standardparameterwerte in ES6 und höher definieren
function getInfo (name, year = 2018, color = 'blue') {
// function body here...
}
Probieren Sie es auf CodePen aus
So einfach ist das.
Wenn die Werte year und color in den Funktionsaufruf übergeben werden, überschreiben die als Argumente übergebenen Werte die in der Funktionsdefinition definierten Parameter. Dies funktioniert genau wie bei den ES5-Mustern, aber ohne all diesen zusätzlichen Code. Viel einfacher zu warten und viel einfacher zu lesen.
Dieses Feature kann für jeden der Parameter im Funktionskopf verwendet werden, sodass Sie einen Standardwert für den ersten Parameter zusammen mit zwei weiteren erwarteten Werten festlegen können, die keine Standardwerte haben
function getInfo (name = 'Pat', year, color) {
// function body here...
}
Umgang mit ausgelassenen Werten
Beachten Sie, dass Sie in einem solchen Fall wie dem obigen, wenn Sie das optionale Argument name weglassen möchten (und somit den Standardwert verwenden), aber year und color einschließen möchten, undefined als Platzhalter für das erste Argument übergeben müssen.
getInfo(undefined, 1995, 'Orange');
Wenn Sie dies nicht tun, wird logischerweise immer angenommen, dass der erste Wert name ist.
Das Gleiche gilt, wenn Sie das Argument year (das zweite) weglassen möchten, aber die anderen beiden einschließen möchten (vorausgesetzt natürlich, dass der zweite Parameter optional ist).
getInfo('Charlie', undefined, 'Pink');
Ich sollte auch erwähnen, dass das Folgende unerwartete Ergebnisse liefern kann
function getInfo (name, year = 1965, color = 'blue') {
console.log(year); // null
}
getInfo('Frankie', null, 'Purple');
Probieren Sie es auf CodePen aus
In diesem Fall habe ich das zweite Argument als null übergeben, was einige dazu verleiten könnte zu glauben, der Wert von year innerhalb der Funktion sei 1965, was der Standardwert ist. Aber das passiert nicht, weil null als gültiger Wert betrachtet wird. Und das ergibt Sinn, denn laut Spezifikation wird null von der JavaScript-Engine als die absichtliche Abwesenheit eines Objektwerts betrachtet, während undefined als etwas betrachtet wird, das zufällig auftritt (z. B. wenn eine Funktion keinen Rückgabewert hat, gibt sie undefined zurück).
Stellen Sie also sicher, dass Sie undefined und nicht null verwenden, wenn der Standardwert verwendet werden soll. Natürlich kann es Fälle geben, in denen Sie null verwenden und dann den null-Wert im Funktionskörper behandeln möchten, aber Sie sollten sich dieser Unterscheidung bewusst sein.
Standardparameterwerte und das arguments-Objekt
Ein weiterer erwähnenswerter Punkt ist die Beziehung zum arguments-Objekt. Das arguments-Objekt ist ein Array-ähnliches Objekt, das innerhalb des Körpers einer Funktion zugänglich ist und die an eine Funktion übergebenen Argumente repräsentiert.
Im Nicht-Strict-Modus spiegelt das arguments-Objekt alle Änderungen wider, die an den Argumentwerten innerhalb des Funktionskörpers vorgenommen werden. Zum Beispiel
function getInfo (name, year, color) {
console.log(arguments);
/*
[object Arguments] {
0: "Frankie",
1: 1987,
2: "Red"
}
*/
name = 'Jimmie';
year = 1995;
color = 'Orange';
console.log(arguments);
/*
[object Arguments] {
0: "Jimmie",
1: 1995,
2: "Orange"
}
*/
}
getInfo('Frankie', 1987, 'Red');
Probieren Sie es auf CodePen aus
Beachten Sie im obigen Beispiel, dass, wenn ich die Werte der Funktionsparameter ändere, diese Änderungen im arguments-Objekt widergespiegelt werden. Dieses Feature wurde als problematischer denn vorteilhafter angesehen, daher ist im Strict-Modus das Verhalten anders.
function getInfo (name, year, color) {
'use strict';
name = 'Jimmie';
year = 1995;
color = 'Orange';
console.log(arguments);
/*
[object Arguments] {
0: "Frankie",
1: 1987,
2: "Red"
}
*/
}
getInfo('Frankie', 1987, 'Red');
Probieren Sie es auf CodePen aus
Wie im Demo gezeigt, behält das arguments-Objekt im Strict-Modus seine ursprünglichen Werte für die Parameter bei.
Damit kommen wir zur Verwendung von Standardparametern. Wie verhält sich das arguments-Objekt, wenn das Feature für Standardparameter verwendet wird? Schauen Sie sich den folgenden Code an
function getInfo (name, year = 1992, color = 'Blue') {
console.log(arguments.length); // 1
console.log(year, color);
// 1992
// "Blue"
year = 1995;
color = 'Orange';
console.log(arguments.length); // Still 1
console.log(arguments);
/*
[object Arguments] {
0: "Frankie"
}
*/
console.log(year, color);
// 1995
// "Orange"
}
getInfo('Frankie');
Probieren Sie es auf CodePen aus
In diesem Beispiel gibt es ein paar Dinge zu beachten.
Erstens ändert die Einbeziehung von Standardparametern nichts am arguments-Objekt. Wenn ich also, wie in diesem Fall, nur ein Argument im Funktionsaufruf übergebe, enthält das arguments-Objekt ein einzelnes Element – auch wenn Standardparameter für die optionalen Argumente vorhanden sind.
Zweitens verhält sich das arguments-Objekt bei vorhandenen Standardparametern im Strict-Modus und im Nicht-Strict-Modus immer gleich. Das obige Beispiel ist im Nicht-Strict-Modus, der es normalerweise erlaubt, das arguments-Objekt zu ändern. Aber das passiert nicht. Wie Sie sehen können, bleibt die Länge von arguments nach Änderung der Werte gleich. Auch wenn das Objekt selbst geloggt wird, ist nur der Wert von name vorhanden.
Ausdrücke als Standardparameter
Das Feature für Standardparameter ist nicht auf statische Werte beschränkt, sondern kann einen Ausdruck enthalten, der ausgewertet wird, um den Standardwert zu bestimmen. Hier ist ein Beispiel, das einige der möglichen Dinge demonstriert.
function getAmount() {
return 100;
}
function getInfo (name, amount = getAmount(), color = name) {
console.log(name, amount, color)
}
getInfo('Scarlet');
// "Scarlet"
// 100
// "Scarlet"
getInfo('Scarlet', 200);
// "Scarlet"
// 200
// "Scarlet"
getInfo('Scarlet', 200, 'Pink');
// "Scarlet"
// 200
// "Pink"
Probieren Sie es auf CodePen aus
Im obigen Code sind ein paar Dinge zu beachten. Erstens erlaube ich dem zweiten Parameter, wenn er nicht im Funktionsaufruf enthalten ist, durch die Funktion getAmount() ausgewertet zu werden. Diese Funktion wird nur aufgerufen, wenn kein zweites Argument übergeben wird. Dies ist im zweiten Aufruf von getInfo() und der anschließenden Protokollierung ersichtlich.
Der nächste wichtige Punkt ist, dass ich einen vorherigen Parameter als Standard für einen anderen Parameter verwenden kann. Ich bin mir nicht ganz sicher, wie nützlich das wäre, aber es ist gut zu wissen, dass es möglich ist. Wie Sie im obigen Code sehen können, setzt die Funktion getInfo() den dritten Parameter (color) gleich dem Wert des ersten Parameters (name), wenn der dritte Parameter nicht enthalten ist.
Und natürlich, da es möglich ist, Funktionen zur Bestimmung von Standardparametern zu verwenden, können Sie auch einen vorhandenen Parameter in eine Funktion übergeben, die als späterer Parameter verwendet wird, wie im folgenden Beispiel.
function getFullPrice(price) {
return (price * 1.13);
}
function getValue (price, pricePlusTax = getFullPrice(price)) {
console.log(price.toFixed(2), pricePlusTax.toFixed(2))
}
getValue(25);
// "25.00"
// "28.25"
getValue(25, 30);
// "25.00"
// "30.00"
Probieren Sie es auf CodePen aus
Im obigen Beispiel führe ich eine rudimentäre Steuerberechnung in der Funktion getFullPrice() durch. Wenn diese Funktion aufgerufen wird, verwendet sie den vorhandenen Parameter price als Teil der Auswertung von pricePlusTax. Wie bereits erwähnt, wird die Funktion getFullPrice() nicht aufgerufen, wenn ein zweites Argument an getValue() übergeben wird (wie im zweiten Aufruf von getValue() gezeigt).
Zwei Dinge, die man im Hinterkopf behalten sollte, in Bezug auf das Obige. Erstens muss der Funktionsaufruf im Ausdruck für den Standardparameter die Klammern enthalten, sonst erhalten Sie eine Funktionsreferenz anstelle einer Auswertung des Funktionsaufrufs.
Zweitens können Sie mit Standardparametern nur auf vorherige Parameter verweisen. Mit anderen Worten, Sie können den zweiten Parameter nicht als Argument in einer Funktion verwenden, um den Standardwert des ersten Parameters zu bestimmen.
// this won't work
function getValue (pricePlusTax = getFullPrice(price), price) {
console.log(price.toFixed(2), pricePlusTax.toFixed(2))
}
getValue(25); // throws an error
Probieren Sie es auf CodePen aus
Ähnlich wie Sie es erwarten würden, können Sie von einem Funktionsparameter nicht auf eine Variable zugreifen, die im Funktionskörper definiert ist.
Fazit
Das sollte so ziemlich alles abdecken, was Sie wissen müssen, um das Beste aus der Verwendung von Standardparametern in Ihren Funktionen in ES6 und höher herauszuholen. Das Feature selbst ist in seiner einfachsten Form recht einfach zu verwenden, aber wie ich hier besprochen habe, gibt es einige Details, die es wert sind, verstanden zu werden.
Wenn Sie mehr zu diesem Thema lesen möchten, hier sind einige Quellen
- Understanding ECMAScript 6 von Nicholas Zakas. Dies war meine Hauptquelle für diesen Artikel. Nicholas ist definitiv mein Lieblingsautor für JavaScript.
- Arguments-Objekt auf MDN
- Standardparameter auf MDN
Chrome hat das tatsächlich unterstützt, bevor es Teil eines Standards war. Ich habe das Feature genutzt, ohne zu wissen, dass es Chrome-spezifisch war, weil es mir immer vorkam, als sollte jede Sprache das haben und es schien zu funktionieren. Dann stellte ich fest, dass IE nicht funktionierte und ich hatte eine Heidenangst, das herauszufinden, bis ein Kollege bemerkte, dass das, was ich verwendete, technisch kein gültiges JavaScript war, obwohl Chrome es zum Laufen brachte. Gut zu sehen, dass es offiziell wird. Das Typeof-Muster am Anfang von Funktionen fühlte sich immer so unzusammenhängend an.
Sollte das erste Codebeispiel unter #default-parameter-values-and-the-arguments-object nach der Änderung der Werte nicht Folgendes ausgeben, wie es auf CodePen der Fall ist?
Ja, jetzt behoben. Entschuldigung, ich glaube, das war ein Kopierfehler, wie ein anderer, auf den hingewiesen wurde.
Sieht nach einem Tippfehler aus?
getValue(25, 30);
// „25.00“
// „28.25“ – sollte 30.00 sein
Ja, es ist behoben. Danke!
Sie haben Standard-Benannte Parameter mit Objekt-Destrukturierung übersprungen.
Oder vielleicht ein praktischeres Beispiel
Schön, danke. Ich habe mich nicht viel mit Destrukturierung beschäftigt (nur oberflächlich), daher könnte ich zu diesem Thema nicht viel sagen. Aber danke, dass Sie es in die Diskussion eingebracht haben.
nette Informationen übrigens! super nützlich
Bevor es Standardparameter gab, habe ich wirklich bevorzugt
Da es etwas eleganter ist und
!=sowohl auf undefined als auch auf null prüft (ob es Ihnen gefällt, wenn Sie sich nur für undefined interessieren), und es nicht das Falsy-Wert-Problem hat, das||hat.Einige der erwarteten Ausgaben, die als Kommentare in den Snippets geschrieben sind, sind falsch, Sie sollten das vielleicht noch einmal überprüfen.
Danke. Es waren nur die Kommentare in den Demos, sie sind jetzt alle korrekt. Meistens nur Kopierfehler, die Überbleibsel von geänderten Codes in der Live-Demo selbst waren.