求问一段js代码的执行过程

var a={n:1}
var b=a;
a.x=a={n:2}
console.log(a)//{n:2}
console.log(a.x)//undefined
console.log(b)//{ n: 1, x: { n: 2 } } 

我的理解:
a先引用了{a:1}对象,
b又引用了a,
a又改变了引用,指向{a:1},
a.x的赋值过程不理解

阅读 3.2k
5 个回答

https://segmentfault.com/q/10...

by @Lemures

对于 a.x = a = {n:2},楼主原先的思路应该是:

  1. 先把 {n:2} 赋值给 a

  2. 然后再创建 a.x,将 {n:2} 再赋值给 a.x

这样似乎确实说不通 a.x 的值是 undefined,因为 a.x 确实是被赋值了的啊。 可是事实上,a.x 的值却是
undefined。

再来看一下这个: a = a.x = {n:2}的话,按楼主原先的思路应该是:

  1. 先把 {n:2} 赋值给 a.x,那么也就相当于 b.x = {n:2} 啦

  2. 再把 a 重新指向 {n:2}。那么这是后 a.x 的值确实是 undefined,a 对象 {n:2} 中就没有 x 属性嘛。

按楼主的思路,上述两种方式的结果应该是不同的。但事实却是a = a.x = {n:2}和a.x = a =
{n:2}的结果是一致的。所以楼主的那种赋值的思路是不对的。

事实上,解析器在接受到 a = a.x = {n:2} 这样的语句后,会这样做:

  1. 找到 a 和 a.x 的指针。如果已有指针,那么不改变它。如果没有指针,即那个变量还没被申明,那么就创建它,指向 null。 a 是有指针的,指向 {n:1};a.x 是没有指针的,所以创建它,指向 null。

  2. 然后把上面找到的指针,都指向最右侧赋的那个值,即 {n:2}。

所以执行以后,就有了如下的变量关系图。楼主可以慢慢体会下,想通了就很简单的。

我什么也没说我只是答案的搬运工…

给题主提供另一个思路:
js中‘.’运算符的优先级是要高于‘=’的,所以才会有a = a.x = {n:2}和a.x = a ={n:2}的结果是一致的。
知道了这个大前提就好办了
a.x=a={n:2}
拆开来看:
第一步:对象a增加属性x(注意这里还未赋值,只是单纯声明,由于引用关系b也拥有一个未赋值的x属性)
第二步:对象a改变赋值{n:2}(注意这里a的指向和第一步中是不一样的)
第三步:给第一步中的x赋值{n:2},即b.x = {n:2}

最终:a:{n:2} b:{x:{n:2},n:1}

a.x=a={n:2} 这是赋值语句,从右开始,相当于让 a 重新指向一个对象,因为这是一个语句,所以前面的a仍然没有被动态改变,仍然指向的是 前一个对象,但是后面出现的 a 却是已经改变指向的,

  1. console.log(a) 这个a就是指向新的对象。
    2.console.log(a.x) 这个 x 属性相当于是前一个对象的属性,但是 a 是已经改变了的,所以没有这个属性。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题