Skip to main content

连续赋值与求值顺序

 var a = {n:1}
a.x = a = {n:2}
问 a.x 是多少?

解析: 答案: undefined

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

上面代码一个连续赋值的语句,因为. 操作符的优先级比=赋值高,所以代码我们可分成两部分执行。a.x(暂且看成整体 A)和a.x的右边(暂且看成整体 B)

  • 整体 A(a.x ): - 由于优先级高,所以先执行。 - a.x=操作了对象本身,于是去堆内存中寻找是否有x这个属性,没有的话会新增这个属性,并且赋值为undefined注意:即使此时a发生了指向的变化,但也不再影响此刻的a.x了,因为已经对a.x进行了指向的确定,只不过他现在正在等待被赋值。
  • 整体 B(a = {n:2}
    • 赋值表达式是右结合的,从右向左执行。
    • {n:2},会在堆内存中开辟一个新空间来存放{n:2}
    • a={n:2},栈内存a指向{n:2},此时 a 的指向变化了,a被重新赋值,相当把a开辟新空间,和之前 a.x 已经没有关系了

结论:由于a.x一直等待赋值一直被挂起,并且a被重新赋值,旧对象地址并灭有无其他指向,JS 垃圾回收机制会把无用的地址给回收,所以a.x为 undefined

  • 类似问题
var a = {n:1};
var b = a;
a.x = a = {n:2};
问 a.x 是多少?
undefined

结论:由于a.x一直等待赋值一直被挂起,也就是一直保持着{n:1,x:undefined}对象 x 属性的访问。 由于对象{n:1,x:undefined}由于一直有一个b的指向,所以不会被 JS 的垃圾回收机制给回收。 当a被重新赋值,因为 b = a,所以旧a.x变为b.xa对象指向新的引用地址,a.x并不存在所以为 undefined

image.png

a.x = a = {}

var a = {x: #505}; // 地址 #404
var b = a; // b = #404
a.x = a = {x: 2}; // #505
// #404.x = a = #505
// #404.x = #505
// b.x = {x: 2}
console.log(a.x) // 2
console.log(b.x) // 1
// 答案自己在浏览器运行

参考文章: https://blog.csdn.net/qq_33692349/article/details/103943242 > https://www.zhihu.com/question/41220520