JS連続イコールの割当問題

1828 ワード

最近GitHubで面白い問題を発見しました.
var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};
console.log(foo.x);  // undefined
console.log(bar); //  Object {n: 1, x: {n:2}}
運転結果はfoo.xの値がundefinedであることを示しています.分析過程は以下の通りです.
ECMAScript仕様によると、
  • Let lref be the relt of evaluating LeftHandSideExpressition.
  • ReturnIfAbrappt.
  • Let rref be the result of evaluating Asignments Expressition.
  • Let rval be GetValue.[…]
  • 大体の意味は、A=Bのような表現については、まずA式を計算し、lrefを得て、計算式Bを計算し、Bの値rvalを得て、rvalをlrefに割り当てた変数をrvalに返します.
    JSの割当表現は右結合なので、foo.x=foo={n:2}はfoo.x=(foo={n:2}に等しいです.
    計算順序によって、
  • は、括弧内の値を計算し、foo.xに割り当てます.
  • はfoo.x={n:2}を得て、同時にbar.x={n:2}を得て、左の最初の等号の計算は終わります.
  • は次に、括弧内の表現、すなわちfoo={n:2}を計算する.
  • fooは新しいオブジェクトに与えられ、元のオブジェクトの参照ではなく、{n:2}を指していますので、foo.xはundefinedを得ていますが、barは元のオブジェクトを指していますので、bar値は変わりません.
  • このセグメントのコードは以下のコードと同じです.
    var foo = {n: 1};
    var bar = foo;
    var foo1 = {n: 2};
    foo.x = foo1;
    foo = foo1;
    console.log(foo.x,bar);