次の場合に実行される部分を確認するためにブラケット表記内のコンマ演算子を利用すると、操作の順序がより明確になります。
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
スペックを見る:
生産AssignmentExpression : LeftHandSideExpression = AssignmentExpression
は次のように評価されます。
LeftHandSideExpressionを評価した結果をlrefとします。
rrefを、AssignmentExpressionを評価した結果とします。
rvalをとしますGetValue(rref)
。
次の場合にSyntaxError例外をスローします...(無関係)
を呼び出しPutValue(lref, rval)
ます。
PutValue
投げるのはTypeError
:
OとするToObject(base)
。
[[CanPut]]
引数PでO の内部メソッドを呼び出した結果がfalseの場合
a。Throwがtrueの場合、TypeError例外をスローします。
のプロパティに何も割り当てることができませんundefined
-の[[CanPut]]
内部メソッドundefined
は常に戻りfalse
ます。
換言すれば、インタプリタが左側を解析し、次に右側を解析し、次に左側のプロパティはに割り当てることができない場合にエラーをスロー。
あなたがするとき
a.x.y = b.e = 1
左側は、が呼び出されるまで正常に解析さPutValue
れます。.x
プロパティが評価されるという事実undefined
は、右側が解析されるまで考慮されません。インタプリタはそれを「未定義のプロパティ "y"にいくつかの値を割り当てる」と見なし、undefined
内部でのみスローするプロパティに割り当てPutValue
ます。
対照的に:
a.x.y.z = b.e = 1
インタプリタはz
、最初にa.x.y
値に解決する必要があるため、プロパティに割り当てようとするポイントに到達しません。a.x.y
(にさえundefined
)値に解決される場合、それは問題ありません- PutValue
上記のように内部でエラーがスローされます。ただし、でプロパティにアクセスできないため、アクセス a.x.y
するとエラーがスローy
されundefined
ます。
b.z = 1
とb.e = 1
最初の(上の右結合性を与えられた実行=
し、)a.x.y.z = ...
実行し、失敗します。なぜb
割り当てが1つの場合に合格し、他の場合に合格しないのですか