JavaScriptは割り当ての左側をいつどの時点で決定しますか?右側が評価される前か後ですか?割り当て時のJavaScriptの評価順序
たとえば、このコードは何をしますか?
var arr = [{thing:1},{thing:2},{thing:3},{last:true}];
arr[arr.length - 1].newField = arr.pop();
JavaScriptは割り当ての左側をいつどの時点で決定しますか?右側が評価される前か後ですか?割り当て時のJavaScriptの評価順序
たとえば、このコードは何をしますか?
var arr = [{thing:1},{thing:2},{thing:3},{last:true}];
arr[arr.length - 1].newField = arr.pop();
割り当て演算子の左辺が最初に評価されます。 ES2015のよう
本の仕様は"Runtime Semantics: Evaluation" portion of the "Assignment Operators" sectionに見出すことができ、非常に大まかようにまとめることができる:
例に関しては、配列に関しては、それは壊れたように見えるかもしれません最初の最後の項目を最終項目の項目に割り当てますが、これはLHSではなくRHSが最初に評価された場合にのみ発生します。
実際には、左端から最初の最後のオブジェクト{last:true}
への参照が最初に生成されます。この後、array.pop()
は配列の最後から同じオブジェクトを削除した後にそのオブジェクトを返します。割り当てが行われ、オブジェクトはobj = {last:true, newField:obj}
のようになります。
function pseudoAssignment() {
// left-hand side evaluated first
var lhsObj = arr[arr.length - 1];
var lhsKey = 'newField';
// then the right-hand side
var rhsVal = arr.pop();
// then the value from RHS is assigned to what the LHS references
lhsObj[lhsKey] = rhsVal;
// `(a = b)` has a value just like `(a + b)` would
return rhsVal;
}
var arr = [{thing:1},{thing:2},{thing:3},{last:true}];
_lastObj = arr[arr.length - 1];
// `arr[arr.length - 1].newField = arr.pop();`
_result = pseudoAssignment();
console.assert(_lastObj.newField === _lastObj,
"The last object now contains a field recursively referencing itself.")
console.assert(_result === _lastObj,
"The assignment's result was the object that got popped.")
console.assert(arr.indexOf(_lastObj) === -1,
"The popped object is no longer in the array.")
:obj
への参照が
ではなく、コードのうちの割り当てを拡大し、我々は行動を確認することができますので、カップルの余分な変数を追加し、元の例に保管しなかったので、このようになります。この割り当て時に何が起こっているかを監視するための良い方法は、アレイ上のプロキシを定義している:
var arr = [{thing:1},{thing:2},{thing:3},{last:true}];
arr = new Proxy(arr, {
get: function (obj, key) {
console.log('getting ', key);
return obj[key];
},
set: function (obj, key, value) {
console.log('setting ', key, ' to ', value);
return obj[key] = value;
}
});
arr[arr.length - 1].newField = arr.pop();
これで、アレイプロパティ(数値インデックスを含むlength
およびpop
メソッドを含む)にアクセスしたとき、およびそれらの設定時にコンソールが表示されます。
最初の2行は左側が最初に評価されることを示す:
を他のラインは
pop
の実行中に生成される3
を取得長
を得る:
ポップアップ
長さを取得
設定長さを3に設定