Die destrukturierende Zuweisung ermöglicht es, Daten aus Arrays oder Objekten zu extrahieren, und zwar mit Hilfe einer Syntax, die der Konstruktion von Array- und Objekt-Literalen nachempfunden ist.
Syntax
[a, b] = [1, 2] [a, b, ...rest] = [1, 2, 3, 4, 5] {a, b} = {a:1, b:2} {a, b, ...rest} = {a:1, b:2, c:3, d:4} //ES7
{a, b} = {a:1, b:2}
ist keine gültige Syntax, die für sich allein stehen kann, da {a, b}
auf der linken Seite als Block und nicht als Objekt-Literal angesehen wird.
Andererseits ist die Form ({a, b} = {a:1, b:2})
gültig, da diese der var {a, b} = {a:1, b:2}
Form entspricht.
Beschreibung
Die Objekt- und Array-Literal Ausdrücke stellen einen einfachen Weg zur Verfügung um ad hoc Packages von Daten anzulegen. Wenn man einmal ein solches Datenpackage angelegt hat kann man es so verwenden wir man willl. Man kann es sogar aus Funktionen zurückgeben.
Besonders nützlich ist bei der destrukturierende Zuweisung dass man eine ganze Struktur mit einem einzelnen Statement einlesen kann. Es gibt jedoch eine ganze Zahl weiterer interessanter Sachen, die man damit machen kann, wie in den Beispielen weiter unten gezeigt wird.
Diese Fähigkeit ist ähnlich in Sprachen wie Perl und Python vorhanden.
Array-Destrukturierung
Einfaches Beispiel
var foo = ["one", "two", "three"]; // ohne Destrukturierung var one = foo[0]; var two = foo[1]; var three = foo[2]; // mit Destrukturierung var [one, two, three] = foo;
Zuweisung ohne Deklaration
Eine destrukturierende Zuweisung kann ohne Deklaration im Zuweisungsstatement vorgenommen werden.
var a, b; [a, b] = [1, 2];
Variablen tauschen
Nach Ausführung dieses Codes ist b == 1 und a == 3. Ohne destrukturierende Zuweisung benötigt man für den Tausch zweier Werte eine temporäre Variable (oder, in manchen Low-level Sprachen, den XOR-swap Trick).
var a = 1; var b = 3; [a, b] = [b, a];
Mehrere Werte zurückgeben
Dank der destrukturierenden Zuweisung können Funktionen mehrere Werte zurückgeben. Obwohl es auch immer möglich ist einfach ein Array zurückzugeben bietet dies weitere Flexibilität.
function f() { return [1, 2]; }
Wie man sieht werden die Ergebnisse in einer Array-artigen Notation zurückgegeben, und zwar mit allen Werten, die zurückgegeben werden sollen, in eckigen Klammern. So kann man kann eine beliebige Zahl an Ergebnissen zurückgeben. In diesem Beispiel gibt f()
die Werte [1, 2]
als seine Ausgabe zurück.
var a, b; [a, b] = f(); console.log("A ist " + a + " B ist " + b);
Das Statement [a, b] = f()
weist die Ergebnisse der Funktion den Variablen, die sich in den eckigen Klammern befinden, in dieser Reihenfolge zu: a wird auf 1 gesetzt und b wird auf 2 gesetzt.
Man kann die Rückgabewere auch als Array erhalten:
var a = f(); console.log("A ist " + a);
In diesem Fall ist a ein Array das die Werte 1 und 2 enthält.
Rückgabewerte teilweise ignorieren
Man kann auch Rückgabewerte, an denen man nicht interessiert ist, ignorieren:
function f() { return [1, 2, 3]; } var [a, , b] = f(); console.log("A ist " + a + " B ist " + b);
Nach Ausführung dieses Codes ist a gleich 1 und b ist 3. Der Wert 2 ist ignoriert. Auf diese Art kann man jegliche (auch alle) zurückgegebene Werte ignorieren. Zum Beispiel:
[,,] = f();
Einzelne Treffer aus den Ergebnis eines regulären Ausdrucks herausziehen
Wenn die Methode exec()
für reguläre Ausdrücke einen Treffer ("match") findet, gibt sie ein Array zurück das erstens den gesamten, passenden Teil des Strings und dann die Teile des Strings enthält, die den einzelnen geklammerten Gruppen im regulären Ausdruck entsprechen. Die destrukturierende Zuweisung erlaubt es die Teile aus diesem Array auf einfache Art herauszuziehen, wobei der String mit dem kompletten Treffer ignoriert werden kann falls er nicht benötigt wird.
var url = "https://developer.mozilla.org/en-US/Web/JavaScript"; var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url); var [, protocol, fullhost, fullpath] = parsedURL; console.log(protocol); // loggt "https"
Object-Destrukturierung
Einfaches Beispiel
var o = {p: 42, q: true}; var {p, q} = o; console.log(p); // 42 console.log(q); // true // Weise neue Variablennamen zu var {p: foo, q: bar} = o; console.log(foo); // 42 console.log(bar); // true
Zuweisung ohne Deklaration
Die destrukturierende Zuweisung kann ohne eine Deklaration im Zuweisungs-Statement durchgeführt werden.
var a, b; ({a, b} = {a:1, b:2});
Die ( .. )
um das Zuweisungs-Statement werden benötigt wenn man die destrukturierende Zuweisung mit Objekt-Literalen ohne eine Deklaration durchführen möchte.
Defaultwerte für Funktionsargumente
ES5 Version
function drawES5Chart(options) { options = options === undefined ? {} : options; var size = options.size === undefined ? 'big' : options.size; var cords = options.cords === undefined ? { x: 0, y: 0 } : options.cords; var radius = options.radius === undefined ? 25 : options.radius; console.log(size, cords, radius); // jetzt zeichnen wir endlich ein paar Charts } drawES5Chart({ cords: { x: 18, y: 30 }, radius: 30 });
ES6 Version
function drawES6Chart({size: size = 'big', cords: cords = { x: 0, y: 0 }, radius: radius = 25} = {}) { console.log(size, cords, radius); // zeichne ein paar Charts } drawES6Chart({ cords: { x: 18, y: 30 }, radius: 30 });
In Firefox sind Defaultwerte für destrukturierende Zuweisungen noch nicht implementiert: var { x = 3 } = {} und var [foo = "bar"] = []. Siehe Bug 932080 für destrukturierte Defaultwerte in Funktionen.
Laden von Modulen (non-ES6)
Destrukturierung kann dabei helfen einen bestimmte Teilmenge eines non-ES6 Moduls zu laden, wie es z.B. im Add-on SDK gemacht wird:
const { Loader, main } = require('toolkit/loader');
Destrukturierung von verschachtelten Objekten und Arrays
var metadata = { title: "Scratchpad", translations: [ { locale: "de", localization_tags: [ ], last_edit: "2014-04-14T08:43:37", url: "/de/docs/Tools/Scratchpad", title: "JavaScript-Umgebung" } ], url: "/en-US/docs/Tools/Scratchpad" }; var { title: englishTitle, translations: [{ title: localeTitle }] } = metadata; console.log(englishTitle); // "Scratchpad" console.log(localeTitle); // "JavaScript-Umgebung"
"for of" Iteration und Destrukturierung
var people = [ { name: "Mike Smith", family: { mother: "Jane Smith", father: "Harry Smith", sister: "Samantha Smith" }, age: 35 }, { name: "Tom Jones", family: { mother: "Norah Jones", father: "Richard Jones", brother: "Howard Jones" }, age: 25 } ]; for (var {name: n, family: { father: f } } of people) { console.log("Name: " + n + ", Father: " + f); } // "Name: Mike Smith, Father: Harry Smith" // "Name: Tom Jones, Father: Richard Jones"
Herausziehen einzelner Felder von Objekten, die als Funktionsparameter übergeben werden
function userId({id}) { return id; } function whois({displayName: displayName, fullName: {firstName: name}}){ console.log(displayName + " is " + name); } var user = { id: 42, displayName: "jdoe", fullName: { firstName: "John", lastName: "Doe" } }; console.log("userId: " + userId(user)); // "userId: 42" whois(user); // "jdoe is John"
Dies ermittelt id
, displayName
und firstName
vom user Objekt und gibt diese aus.
Berechnete Namen von Objekt-Eigenschaften und Destrukturierung
Berechnete Eigenschafts-Namen, wie bei Objekt-Literalen, können bei der Destruktierung verwendet werden.
let key = "z"; let { [key]: foo } = { z: "bar" }; console.log(foo); // "bar"
Spezifikationen
Spezifikation | Status | Kommentar |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) Die Definition von 'Destructuring assignment' in dieser Spezifikation. |
Standard | Erstmalige Definition. |
ECMAScript 2016 Draft (7th Edition, ECMA-262) Die Definition von 'Destructuring assignment' in dieser Spezifikation. |
Entwurf |
Browser-Kompatibilität
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Grundlegende Unterstützung | Nicht unterstützt | 2.0 (1.8.1) | Nicht unterstützt | Nicht unterstützt | 7.1 |
Berechnete Eigenschafts-Namen | Nicht unterstützt | 34 (34) | Nicht unterstützt | Nicht unterstützt | Nicht unterstützt |
Spread-Operator | ? | 34 (34) | ? | ? | ? |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Grundlegende Unterstützung | Nicht unterstützt | Nicht unterstützt | 1.0 (1.0) | Nicht unterstützt | Nicht unterstützt | 8 |
Berechnete Eigenschafts-Namen | Nicht unterstützt | Nicht unterstützt | 34.0 (34) | Nicht unterstützt | Nicht unterstützt | Nicht unterstützt |
Spread-Operator | ? | ? | 34.0 (34) | ? | ? | ? |
Firefox-spezifische Anmerkungen
- Firefox stellte in JS1.7 für Destrukturierung eine nicht-standardisierte Spracherweiterung zur Verfügung. Diese Extension wurde in Gecko 40 (Firefox 40 / Thunderbird 40 / SeaMonkey 2.37) entfernt. Siehe Bug 1083498.
- Beginnend mit Gecko 41 (Firefox 41 / Thunderbird 41 / SeaMonkey 2.38) und ensprechend der ES6 Spezifikation werden nun geklammerte Destrukturierungs-Muster wie
([a, b]) = [1, 2]
or({a, b}) = { a: 1, b: 2 }
als ungültig angesehen und werfen einenSyntaxError
. Siehe Jeff Walden's Blog-Post und Bug 1146136 für weitere Details.