Javascript代码技巧:foo.x的价值是什么
我在Github前端面试题集合中遇到过这个问题:
var foo = {n: 1}; var bar = foo; foo.x = foo = {n: 2};问题:foo.x的价值是什么?
 答案是undefined 。 
我已经做了一些研究,我明白这个问题是(纠正我,如果我错了):
-  var foo = {n: 1};声明一个属性n等于1的对象foo。
-  var bar = foo;声明一个与foo相同的对象。
-  foo.x = foo = {n: 2};我相信它等于foo.x = (foo = {n: 2});
-  然后我得到foo.x等于undefined。 但是,bar.x的值是对象{n:2}。
 如果bar和foo引用同一个对象,为什么bar.x得到值,而foo.x是undefined ? 在foo.x = foo = {n: 2};发生了什么?  ? 
 foo.x = foo = {n: 2}; 
 确定foo.x引用{n: 1}对象的属性x ,将{n: 2}分配给foo ,并将foo – {n: 2}的新值赋给{n: 1}对象。 
 重要的是, foo.x引用的foo是在foo更改之前确定的。 
请参阅ES5规范的第11.13.1节 :
让lref是评估LeftHandSideExpression的结果。
让rref是评估AssignmentExpression的结果。
赋值运算符从右到左关联,因此您可以:
 foo.x = (foo = {n: 2}) 
左侧在右侧之前进行评估。
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}} ,而bar仍然指向它。 foo现在指的是{n:2} 。
所以执行foo.x给出了未定义,因为foo中只有一个值是{n:2}。
但是,如果你会尝试执行bar.x它会给{n:2}。 或者如果你只是执行吧,结果将是
对象{n:1,x:Object}
我想我会添加另一个,我发现是有用的方式来思考这个。
 那些最后的variables赋值相当于写入bar.x = foo = {n:2};  ,因为这些variables只是在内存中引用相同的东西。 
 换句话说, foo和bar起初都是引用同一个对象{n:1} 。 当您使用foo.x = ,您正在访问{n:1}并向其中添加x属性。 这可以用bar或foo来完成,因为它们都指向内存中的同一个对象! 没什么区别。 
 然后,当你完成这一行, foo.x = foo = {n:2} ,你将通过对象字面值语法在内存中创build另一个全新的对象,并将foo指向该对象{n:2}现在是{n:1, x: {n: 2} 。 不过,这并不影响foo在将x属性添加到它时指向的内容。 
这是相当混乱的,但我认为你有必要考虑一下这样一个事实,即variables只是指向内存中的地方/对象的指针,并且对象文本语法不会改变以前存在的对象(即使它们看起来相似)。 这是创造一个全新的。
对这个问题的接受答案的开始可能也是有帮助的。
对象variables只是对JavaScript中的对象的引用,而不是对象本身。
  var foo = {n: 1} – > foo表示真实对象{n:1} var bar = foo – > bar现在也是对象的引用{n:1} 
 棘手的部分当然是第三行: foo.x = foo = {n: 2} 
 这相当于:( (reference to {n: 1}).x = (foo = {n: 2}) – >在这条线完全评估之后,foo变成对新对象{n:2}的引用。 然而,由于foo在评估线之前引用原始对象{n: 1} ,所以在评估线之后,原始对象{n: 1}变为{n: 1, x: {n: 2}}修改的对象将通过参考bar访问。 如果没有参考栏,则原始对象将被销毁