Javascript代码技巧:foo.x

时间:2015-09-02 00:16:30

标签: javascript object variable-assignment

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

var foo = {n: 1};
var bar = foo;
foo.x = foo = {n: 2};
     

问题: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.xfoo.xundefined时获得了价值? foo.x = foo = {n: 2};中真正发生了什么?

6 个答案:

答案 0 :(得分:48)

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

确定foo.x引用x对象的属性{n: 1},将{n: 2}分配给foo,并指定{{1}的新值} - foo - {n: 2}对象的属性x

重要的是{n: 1}引用的foo是在foo.x更改之前确定的。

请参阅section 11.13.1 of the ES5 spec

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

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

  4.   

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

foo

左手侧在右手侧评估。

答案 1 :(得分:21)

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

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

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

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

因为作业只从右到左发生。所以在这里我们只需要检查foo在执行开始之前是指哪个对象。

解决R.H.S: foo = {n:2} ;现在 foo 指的是 {n:2} ;

回到我们留下的问题:

foo.x = foo;

现在L.H.S上的 foo.x仍然是{n:1} .x ,而R.H.S上的 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:对象}

答案 2 :(得分:4)

我以为我会添加另一个,我发现的是,有用的思考方式。

那些最后的变量赋值等同于写bar.x = foo = {n:2};,因为这些变量只是对内存中同一事物的引用。

换句话说,foobar最初都引用同一个对象{n:1}。当您使用foo.x =时,您正在访问{n:1}并向其添加x属性。这可以使用barfoo来完成,因为它们都指向内存中的同一个对象!没有区别。

然后,当您完成该行foo.x = foo = {n:2}时,您将通过对象文字语法在内存中创建另一个全新对象,并将foo设置为指向那个对象{n:2},而不是现在的{n:1, x: {n: 2}。但是,这并不会影响foox添加.one()属性时指向的内容。

这非常令人困惑,但我认为你认为变量只是指向内存中的位置/对象的指针是有道理的,并且该对象的文字语法不会改变以前存在的对象(即使它们看起来类似)。它创造了一个全新的。

this question的已接受答案的开头也可能有用。

答案 3 :(得分:3)

理解的是,对象变量仅仅是对JavaScript中对象的引用,而不是对象本身。

var foo = {n: 1} - > foo指真实对象{n:1} var bar = foo - > bar现在也是对真实对象的引用{n:1}

棘手的部分当然是第3行: foo.x = foo = {n: 2}

这相当于: (reference to {n: 1}).x = (foo = {n: 2}) - >在完全评估这一行之后,foo成为对象{n:2}的引用;但是,由于foo在评估行之前引用原始对象{n: 1},因此在评估行之后原始对象{n: 1}变为{n: 1, x: [reference to]{n: 2}},并且可以通过参考bar。如果没有参考栏,原始对象将被销毁

答案 4 :(得分:3)

据我了解,表情:

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

与以下内容完全相同:

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

在此之后,很明显:

 bar=={n: 1, x: {n:2}};
 foo=={n:2};
 foo.x==undefined

答案 5 :(得分:0)

我认为在Javascript中,如果对象不为空,则不能为不存在的属性分配值。因此,在这种情况下,foo对象具有一个{n:1}的属性和值对,因此,由于它不为空且不具有ax属性,因此无法分配,但是由于为bar对象分配的值是foo对象,无论foo是什么,它都将具有值