Verwendung von Standardparametern in ES6

Avatar of Louis Lazaris
Louis Lazaris am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

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