Die Reihenfolge der Operationen ist klarer, wenn Sie den Komma-Operator in der Klammer-Notation ausnutzen, um zu sehen, welche Teile ausgeführt werden, wenn:
var a = {}
var b = {}
try{
// Uncaught TypeError: Cannot set property 'y' of undefined
a
[console.log('x'), 'x']
[console.log('y'), 'y']
= (console.log('right hand side'), b.e = 1);
} catch(err) {
console.error(err);
}
console.log(b.e) // 1
var a = {}
var b = {}
try {
// Uncaught TypeError: Cannot read property 'y' of undefined
a
[console.log('x'), 'x']
[console.log('y'), 'y']
[console.log('z'), 'z']
= (console.log('right hand side'), b.e = 1);
} catch(err) {
console.error(err);
}
console.log(b.e) // undefined
Betrachtet man die Spezifikation :
Die Produktion AssignmentExpression : LeftHandSideExpression = AssignmentExpression
wird wie folgt bewertet:
Sei lref das Ergebnis der Auswertung von LeftHandSideExpression.
Sei rref das Ergebnis der Auswertung von AssignmentExpression.
Sei rval GetValue(rref)
.
Eine SyntaxError-Ausnahme auslösen, wenn ... (irrelevant)
Rufen Sie an PutValue(lref, rval)
.
PutValue
ist das, was das wirft TypeError
:
Lass O sein ToObject(base)
.
Wenn das Ergebnis des Aufrufs der [[CanPut]]
internen Methode von O mit dem Argument P falsch ist, dann
ein. Wenn Throw true ist, wird eine TypeError-Ausnahme ausgelöst.
Einer Eigenschaft von kann nichts zugewiesen werden undefined
- die [[CanPut]]
interne Methode von undefined
wird immer zurückgegeben false
.
Mit anderen Worten: parst der Dolmetscher auf die linke Seite, analysiert dann die rechte Seite, dann wirft einen Fehler , wenn die Eigenschaft auf der linken Seite nicht zugeordnet werden können.
Wenn Sie das tun
a.x.y = b.e = 1
Die linke Seite wird erfolgreich analysiert , bis sie PutValue
aufgerufen wird. Die Tatsache, dass die .x
Eigenschaft bewertet wird, undefined
wird erst berücksichtigt, nachdem die rechte Seite analysiert wurde. Der Interpreter sieht es als "Weisen Sie der Eigenschaft" y "von undefined einen Wert zu und weisen Sie einer Eigenschaft zu, die undefined
nur Würfe enthält PutValue
.
Im Gegensatz:
a.x.y.z = b.e = 1
Der Interpreter kommt nie an den Punkt, an dem er versucht, der z
Eigenschaft zuzuweisen , da er zuerst a.x.y
in einen Wert aufgelöst werden muss. Wenn es a.x.y
auf einen Wert (sogar auf undefined
) aufgelöst würde, wäre es in Ordnung - ein Fehler würde PutValue
wie oben hineingeworfen . Der Zugriff a.x.y
löst jedoch einen Fehler aus, da auf die Eigenschaft y
nicht zugegriffen werden kann undefined
.
b.z = 1
undb.e = 1
zuerst ausführen (bei gegebener Rechtsassoziativität=
), danna.x.y.z = ...
ausführen und fehlschlagen; Warum besteht dieb
Aufgabe in einem Fall, in dem anderen jedoch nicht?