JavaScript 代码技巧:foo.x 的值是多少

JavaScript code trick: What's the value of foo.x

我在一个GitHub前端面试题集里发现了这个问题:

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

Question: What is the value of foo.x?

答案是undefined

我做了一些研究,我对这个问题的理解是(如果我错了请纠正我):

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

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

判断foo.x引用了{n: 1}对象的属性x,将{n: 2}赋值给foo,并赋值给foo foo 的新值 – {n: 2} – 到 {n: 1} 对象的 属性 x

重要的是foo.x所指的foo是在foo变化之前就确定的

section 11.13.1 of the ES5 spec:

  1. Let lref be the result of evaluating LeftHandSideExpression.

  2. Let rref be the result of evaluating 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 指的是哪个对象。

关于解决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} } 并且 bar 仍然引用它。 foo 现在指的是 {n:2}

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

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

Object {n: 1, x: Object}

我想我会添加另一个我发现的有用的思考方式。

那些最后的变量赋值相当于写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}。不过,这不会影响 foo 向其添加 x 属性 时指向的内容。

这很令人困惑,但我认为您考虑以下事实是有道理的:变量只是内存中指向 places/objects 的指针,并且对象字面量语法不会更改先前存在的对象(即使他们看起来很相似)。它正在创建一个全新的。

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

需要理解的是,对象变量只是对 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: [reference to]{n: 2}},修改后的对象将可以通过参考 bar。如果没有reference bar,原对象会被销毁

据我理解表达:

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

完全一样:

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

在此之后很明显:

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

我认为在 Javascript 中,您不能为 属性 赋值,如果对象不为空,则该值不存在。所以在这种情况下 foo 对象有一个 属性 和值对,它是 {n:1} 所以因为它不是空的并且它没有 x 属性 ,你不能分配但是因为你分配bar object a value which is foo object , it will have the value whatever the foo is