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 = AssignmentExpressionwird 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).
PutValueist 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 undefinedwird 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 PutValueaufgerufen wird. Die Tatsache, dass die .xEigenschaft bewertet wird, undefinedwird 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 undefinednur 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 zEigenschaft zuzuweisen , da er zuerst a.x.yin einen Wert aufgelöst werden muss. Wenn es a.x.yauf einen Wert (sogar auf undefined) aufgelöst würde, wäre es in Ordnung - ein Fehler würde PutValuewie oben hineingeworfen . Der Zugriff a.x.y löst jedoch einen Fehler aus, da auf die Eigenschaft ynicht zugegriffen werden kann undefined.
b.z = 1undb.e = 1zuerst ausführen (bei gegebener Rechtsassoziativität=), danna.x.y.z = ...ausführen und fehlschlagen; Warum besteht diebAufgabe in einem Fall, in dem anderen jedoch nicht?