2017-07-21 5 views
2

JavaScriptは割り当ての左側をいつどの時点で決定しますか?右側が評価される前か後ですか?割り当て時のJavaScriptの評価順序

たとえば、このコードは何をしますか?

var arr = [{thing:1},{thing:2},{thing:3},{last:true}]; 
arr[arr.length - 1].newField = arr.pop(); 

答えて

2

割り当て演算子の左辺が最初に評価されます。 ES2015のよう

本の仕様は"Runtime Semantics: Evaluation" portion of the "Assignment Operators" sectionに見出すことができ、非常に大まかようにまとめることができる:

  1. を決定するために、RHSを評価基準
  2. を決定するために、LHSを評価
  3. 参照に値を代入する

例に関しては、配列に関しては、それは壊れたように見えるかもしれません最初の最後の項目を最終項目の項目に割り当てますが、これは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.") 
0

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に設定

関連する問題