Objektzerstörung ohne var


97

Warum wirft die Objektzerstörung einen Fehler aus, wenn kein varSchlüsselwort davor steht?

{a, b} = {a: 1, b: 2};

wirft SyntaxError: expected expression, got '='

Die folgenden drei Beispiele funktionieren ohne Probleme

var {a, b} = {a: 1, b: 2};
var [c, d] = [1, 2];
    [e, f] = [1, 2];

Bonusfrage: Warum brauchen wir keine varfür die Array-Destrukturierung?

Ich bin auf das Problem gestoßen, so etwas zu tun

function () {
  var {a, b} = objectReturningFunction();

  // Now a and b are local variables in the function, right?
  // So why can't I assign values to them?

  {a, b} = objectReturningFunction();
}

Antworten:


158

Das Problem ist darauf zurückzuführen, dass die {...}Operatoren in JavaScript mehrere Bedeutungen haben.

Wenn es {am Anfang einer Anweisung angezeigt wird , stellt es immer einen Block dar , dem nicht zugewiesen werden kann. Wenn es später in der Anweisung als Ausdruck angezeigt wird, stellt es ein Objekt dar.

Das varhilft , diese Unterscheidung zu treffen, da sie nicht von einem verfolgt werden kann Statement , ebenso wie die Gruppierung Klammer :

( {a, b} = objectReturningFunction() );

Aus ihren Dokumenten: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Assignment_without_declaration

Hinweise: Die Klammern (...) um die Zuweisungsanweisung sind erforderlich, wenn eine Objektliteral-Destrukturierungszuweisung ohne Deklaration verwendet wird.

{a, b} = {a: 1, b: 2} ist keine gültige eigenständige Syntax, da {a, b} auf der linken Seite als Block und nicht als Objektliteral betrachtet wird.

({A, b} = {a: 1, b: 2}) ist jedoch gültig, ebenso wie var {a, b} = {a: 1, b: 2}

Vor Ihrem (...) Ausdruck muss ein Semikolon stehen. Andernfalls kann eine Funktion in der vorherigen Zeile ausgeführt werden.


Wenn es später in der Anweisung als Ausdruck angezeigt wird, stellt es ein Objekt dar. Bedeutet dies, dass wir niemals einen Blockbereich innerhalb der Gruppierungsklammer haben können
sharad_kalya

Der Tipp für Gruppierungsklammern ist großartig.
James Smith

Dies ist ein genial obskures Stück Wissen, das mich verblüfft hat. Es ermöglicht eine Destrukturierung über den gesamten Bereich hinweg (na ja, irgendwie - Sie müssen Ihre Variablen natürlich immer noch deklarieren). Es löst jedoch die Einschränkung, Promise-Ketten zu verwenden, während mehrere Variablen verwendet werden müssen, die aus einem Schritt einer Promise-Kette in einem anderen aufgelöst wurden, ohne zu viel Chaos zu verursachen. Vielen Dank.
Kevin Teljeur

21

Wenn Sie Javascript ohne Semikolons schreiben , sollte der Syntax "Zuweisung ohne Deklaration" ein Semikolon vorangestellt werden, damit es vorhersehbar funktioniert

let a, b

;({a, b} = objectReturningFunction()) // <-- note the preceding ;

Ich wollte dies nur hervorheben, als es mich erwischte, und hoffentlich anderen Zeit sparen, um herauszufinden, warum es nicht funktioniert und / oder seltsame Ergebnisse mit Code-Formatierern wie prettier.

In der Tat ist es genau dort in der akzeptierten Antwort (letzte Zeile der zitierten Dokumente), aber leicht zu übersehen, besonders ohne ein Beispiel zu sehen!


Ja. Ein Grund für Leute, Semikolons zu verwenden!
jfriend00

0

Hier ist ein anderer Weg:

let {} = {a, b} = objectReturningFunction()

Vorteile:

  • Keine Klammer erforderlich
  • Keine Semikolons erforderlich

Nachteile:

  • Sieht ein bisschen komisch aus, obwohl meiner Meinung nach nicht seltsamer als das !(){...}() IIFE
  • Könnte verwirrend sein, warum es dort ist

Es fühlt sich so an, als wären IIFEs vergleichbarer ;({ a, b })als let {} = { ... }. Netter Trick. :)
Shuckster

@ Proto-n, +1, sehr kluge Idee. Wie bist du darauf gekommen?
Pacerier vor
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.