Javascript代码技巧:foo.x的价值是什么

And*_*yHu 53 javascript object variable-assignment

我在Github前端访谈问题集中遇到了这个问题:

var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};
Run Code Online (Sandbox Code Playgroud)

问题:foo.x的价值是多少?

答案是undefined.

我做了一些研究,我明白这个问题是(如果我错了,请纠正我):

  • var foo = {n: 1};声明一个foo属性n等于1 的对象.
  • var bar = foo;声明了一个bar引用相同对象的对象foo.
  • foo.x = foo = {n: 2}; 我认为这等于 foo.x = (foo = {n: 2});
  • 然后我得到了foo.x平等undefined.但是,值bar.x是对象{n:2}.

如果barfoo是指同一个对象,为什么bar.x得到的价值,同时foo.xundefined?真正发生了foo.x = foo = {n: 2};什么?

Ry-*_*Ry- 51

foo.x = foo = {n: 2};
Run Code Online (Sandbox Code Playgroud)

判定foo.x是指一种属性x的的{n: 1}目的,分配{n: 2}foo,并分配的新值foo- {n: 2}-为属性x的的{n: 1}对象.

重要的是,foofoo.x指的是之前确定foo的变化.

参见ES5规范的第11.13.1节:

  1. lref成为评估LeftHandSideExpression的结果.

  2. rref成为评估AssignmentExpression的结果.

赋值运算符从右到左关联,因此您得到:

foo.x = (foo = {n: 2})
Run Code Online (Sandbox Code Playgroud)

左手侧在右手侧评估.

  • @soulcheck谢谢.所以你的意思是`foo`在赋值后现在是`{n:2}`,但`foo.x`属于旧的'foo = {n:1}'对象,因为`foo`不再存在已被更改为`{n:2}`因此`foo.x`无法赋值,但`bar.x`得到了值,因为`bar`始终存在且从未被更改过?天啊... (4认同)
  • @AndyHu:`foo.x`指的是旧`foo`的`x`.`bar`也指老`foo`.新的`foo`上不存在`x`. (4认同)
  • @soulcheck:这是标准规定的。现在找到重要的部分。(这也是常识所要求的——考虑`(x = {}).y = x`) (2认同)

小智 23

foo.x = foo = {n:2};

这里foo 在赋值之前,即在执行语句之前引用{n:1}对象.

该语句可以重写为foo.x =(foo = {n:2});

在对象术语中,上述语句可以重写为 {n:1} .x =({n:1} = {n:2});

由于分配仅从右到左进行.所以在这里我们只需要检查foo在执行开始之前是指哪个对象.

关于解决RHS: foo = {n:2} ; 现在foo指的是{n:2} ;

回过头来看我们留下的问题:

foo.x = foo;

现在,LHS上的foo.x仍为{n:1} .x,RHS上的foo为{n:2}.

因此,在执行此语句后,{n:1}将成为{n:1,x:{n:2}},并且仍然指向它.凡为FOO现在将参照{N:2} .

所以在执行时foo.x给出了undefined,因为foo中只有1个值是{n:2}.

但是如果您尝试执行bar.x,它将给出{n:2}.或者,如果您只是执行bar,结果将是

对象{n:1,x:Object}


小智 8

据我了解表达:

foo.x = foo = {n: 2};
Run Code Online (Sandbox Code Playgroud)

完全一样:

foo.x = {n: 2} ; 
foo = {n: 2};
Run Code Online (Sandbox Code Playgroud)

在此之后,很明显:

 bar=={n: 1, x: {n:2}};
 foo=={n:2};
 foo.x==undefined
Run Code Online (Sandbox Code Playgroud)