Was ist eine Destrukturierungsaufgabe?
Durch die Destrukturierung der Zuweisung können Sie einer Reihe von Variablen Array- und Objekteigenschaftswerte zuweisen, wobei Sie eine Syntax verwenden, die Array- oder Objektliteralen ähnelt. Diese Syntax ist sehr prägnant und klarer als der herkömmliche Zugriff auf Eigenschaften.
Greifen Sie auf die ersten drei Elemente eines Arrays zu, ohne eine destrukturierende Zuweisung zu verwenden:
var first = someArray[0]; var second = someArray[1]; var third = someArray[2]; var first = someArray[0]; var second = someArray[1]; var third = someArray[2];
Nach der Verwendung der destrukturierenden Zuweisung wird der entsprechende Code prägnanter und lesbarer:
var [first, second, third] = someArray; var [first, second, third] = someArray;
SpiderMonkey (die JavaScript-Engine von Firefox) unterstützt bereits die meisten Funktionen der Destrukturierungszuweisung, jedoch nicht vollständig.
Destrukturierende Zuweisung von Arrays und iterierbaren Objekten
Wir haben oben Beispiele für die Zuweisung einer Array-Destrukturierung gesehen. Die allgemeine Form dieser Syntax ist:
[ variable1, variable2, ..., variableN ] = array; [ variable1, variable2, ..., variableN ] = array;
Dadurch werden die entsprechenden Elemente im Array nacheinander Variable1 bis VariableN zugewiesen. Wenn Sie gleichzeitig Variablen deklarieren müssen, können Sie die Schlüsselwörter var, let oder const vor dem Destrukturierungsausdruck hinzufügen.
var [ variable1, variable2, ..., variableN ] = array; let [ variable1, variable2, ..., variableN ] = array; const [ variable1, variable2, ..., variableN ] = array; var [ variable1, variable2, ..., variableN ] = array; let [ variable1, variable2, ..., variableN ] = array; const [ variable1, variable2, ..., variableN ] = array;
Tatsächlich können Sie jede Tiefe verschachteln:
var [foo, [[bar], baz]] = [1, [[2], 3]]; console.log(foo); // 1 console.log(bar); // 2 console.log(baz); // 3 var [foo, [[bar], baz]] = [1, [[2], 3]]; console.log(foo); // 1 console.log(bar); // 2 console.log(baz); // 3
Außerdem ist es möglich, bestimmte Elemente in einem Array zu überspringen:
var [,,third] = ["foo", "bar", "baz"]; console.log(third); // "baz" var [,,third] = ["foo", "bar", "baz"]; console.log(third); // "baz"
Sie können auch einen Rest-Ausdruck verwenden, um die verbleibenden Elemente in einem Array zu erfassen:
var [head, ...tail] = [1, 2, 3, 4]; console.log(tail); // [2, 3, 4] var [head, ...tail] = [1, 2, 3, 4]; console.log(tail); // [2, 3, 4]
Wenn das Array außerhalb der Grenzen liegt oder auf ein Element zugreift, das nicht im Array vorhanden ist, erhalten Sie denselben Wert wie beim Zugriff über den Array-Index: undefiniert.
console.log([][0]); // undefined var [missing] = []; console.log(missing); // undefined console.log([][0]); // undefined var [missing] = []; console.log(missing); // undefined
Beachten Sie, dass die Methode der Array-Destrukturierung und -Zuweisung auch für durchquerbare Objekte gilt:
function* fibs() { var a = 0; var b = 1; while (true) { yield a; [a, b] = [b, a + b]; } } var [first, second, third, fourth, fifth, sixth] = fibs(); console.log(sixth); // 5 function* fibs() { var a = 0; var b = 1; while (true) { yield a; [a, b] = [b, a + b]; } } var [first, second, third, fourth, fifth, sixth] = fibs(); console.log(sixth); // 5
Destrukturierende Zuordnung von Objekten
Die Objektdestrukturierungszuweisung ermöglicht es Ihnen, Variablen an verschiedene Eigenschaftswerte des Objekts zu binden. Geben Sie den Namen der zu bindenden Eigenschaft an, gefolgt von der zu bindenden Variablen:
var robotA = { name: "Bender" }; var robotB = { name: "Flexo" }; var { name: nameA } = robotA; var { name: nameB } = robotB; console.log(nameA); // "Bender" console.log(nameB); // "Flexo" var robotA = { name: "Bender" }; var robotB = { name: "Flexo" }; var { name: nameA } = robotA; var { name: nameB } = robotB; console.log(nameA); // "Bender" console.log(nameB); // "Flexo"
Wenn der gebundene Attributname mit dem Variablennamen übereinstimmt, der den Attributwert empfängt, gibt es einen weiteren syntaktischen Zucker:
var { foo, bar } = { foo: "lorem", bar: "ipsum" }; console.log(foo); // "lorem" console.log(bar); // "ipsum" var { foo, bar } = { foo: "lorem", bar: "ipsum" }; console.log(foo); // "lorem" console.log(bar); // "ipsum"
Wie Arrays können sie auch verschachtelt werden:
var complicatedObj = { arrayProp: [ "Zapp", { second: "Brannigan" } ] }; var { arrayProp: [first, { second }] } = complicatedObj; console.log(first); // "Zapp" console.log(second); // "Brannigan" var complicatedObj = { arrayProp: [ "Zapp", { second: "Brannigan" } ] }; var { arrayProp: [first, { second }] } = complicatedObj; console.log(first); // "Zapp" console.log(second); // "Brannigan"
Wenn Sie eine Eigenschaft zerstören, die nicht existiert, erhalten Sie undefiniert:
var { missing } = {}; console.log(missing); // undefined var { missing } = {}; console.log(missing); // undefined
Es gibt eine weitere potenzielle Gefahr bei der Verwendung der destrukturierenden Zuweisung von Objekten: Es gibt keine Variablendeklaration (kein Schlüsselwort var, let oder const) während der destrukturierenden Zuweisung:
{ blowUp } = { blowUp: 10 }; // Syntax error { blowUp } = { blowUp: 10 }; // Syntax error
Dies liegt daran, dass die JavaScript-Syntax der Engine mitteilt, dass jede Anweisung, die mit { beginnt, ein Anweisungsblock ist (zum Beispiel ist {console} ein zulässiger Anweisungsblock. Die Lösung besteht darin, die gesamte Anweisung mit einem Klammerpaar zu umschließen: <). 🎜>
({ safe } = {}); // No errors ({ safe } = {}); // No errors
Andere Situationen
Wenn Sie versuchen, null oder undefiniert zu destrukturieren, erhalten Sie einen Typfehler:
var {blowUp} = null; // TypeError: null has no properties var {blowUp} = null; // TypeError: null has no properties
var {wtf} = NaN; console.log(wtf); // undefined var {wtf} = NaN; console.log(wtf); // undefined
Standardwert
var [missing = true] = []; console.log(missing); // true var { message: msg = "Something went wrong" } = {}; console.log(msg); // "Something went wrong" var { x = 3 } = {}; console.log(x); // 3 var [missing = true] = []; console.log(missing); // true var { message: msg = "Something went wrong" } = {}; console.log(msg); // "Something went wrong" var { x = 3 } = {}; console.log(x); // 3
Praktische Anwendung
Funktionsparameter
function removeBreakpoint({ url, line, column }) { // ... } function removeBreakpoint({ url, line, column }) { // ... }
Konfigurationsobjekt
Um das obige Beispiel zu verbessern, können wir Standardwerte für die zu zerstörenden Objekteigenschaften bereitstellen. Dies ist sehr praktisch für Objekte, die als Konfigurationsparameter verwendet werden, da viele Konfigurationselemente einen angemessenen Standardwert haben. Der zweite Parameter der Ajax-Methode von jQuery ist beispielsweise ein Konfigurationsobjekt, das wir wie folgt implementieren können:
jQuery.ajax = function (url, { async = true, beforeSend = noop, cache = true, complete = noop, crossDomain = false, global = true, // ... more config }) { // ... do stuff }; jQuery.ajax = function (url, { async = true, beforeSend = noop, cache = true, complete = noop, crossDomain = false, global = true, // ... more config }) { // ... do stuff };
Wird mit Iteratoren verwendet
var map = new Map(); map.set(window, "the global"); map.set(document, "the document"); for (var [key, value] of map) { console.log(key + " is " + value); } // "[object Window] is the global" // "[object HTMLDocument] is the document" var map = new Map(); map.set(window, "the global"); map.set(document, "the document"); for (var [key, value] of map) { console.log(key + " is " + value); } // "[object Window] is the global" // "[object HTMLDocument] is the document"
for (var [key] of map) { // ... } for (var [key] of map) { // ... } 只遍历值: for (var [,value] of map) { // ... } for (var [,value] of map) { // ... }
Mehrere Werte zurückgeben
Gibt ein Array zurück und extrahiert den Rückgabewert durch Destrukturierungszuweisung:
function returnMultipleValues() { return [1, 2]; } var [foo, bar] = returnMultipleValues(); function returnMultipleValues() { return [1, 2]; } var [foo, bar] = returnMultipleValues();
function returnMultipleValues() { return { foo: 1, bar: 2 }; } var { foo, bar } = returnMultipleValues(); function returnMultipleValues() { return { foo: 1, bar: 2 }; } var { foo, bar } = returnMultipleValues();
function returnMultipleValues() { return { foo: 1, bar: 2 }; } var temp = returnMultipleValues(); var foo = temp.foo; var bar = temp.bar; function returnMultipleValues() { return { foo: 1, bar: 2 }; } var temp = returnMultipleValues(); var foo = temp.foo; var bar = temp.bar;
function returnMultipleValues(k) { k(1, 2); } returnMultipleValues((foo, bar) => ...); function returnMultipleValues(k) { k(1, 2); } returnMultipleValues((foo, bar) => ...);
导入 CommonJS 模块的指定部分
还没使用过 ES6 的模块吧,那至少使用过 CommonJS 吧。当导入一个 CommonJS 模块 X 时,模块提供的方法也许多余你实际使用的。使用解构赋值,你可以明确指定你需要使用模块的哪些部分:
const { SourceMapConsumer, SourceNode } = require("source-map"); const { SourceMapConsumer, SourceNode } = require("source-map");
如果你使用 ES6 的模块机制,你可以看到 import 声明时有一个类似的语法。
结论
我们看到,解构赋值在很多场景下都很实用。在 Mozilla,我们已经有很多经验。Lars Hansen 在 10 年前就向 Opera 引入了解构赋值,Brendan Eich 在稍微晚点也给 Firefox 添加了支持,最早出现在 Firefox 2 中。因此,解构赋值已经渗透到我们每天对 JS 的使用中,悄悄地使我们的代码更简短、整洁。