Destruktierende Zuweisung

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 einen SyntaxError. Siehe Jeff Walden's Blog-Post und Bug 1146136 für weitere Details.

Siehe auch

Schlagwörter des Dokuments und Mitwirkende

 Mitwirkende an dieser Seite: sbusch
 Zuletzt aktualisiert von: sbusch,