连续赋值与求值顺序
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.x
,a
对象指向新的引用地址,a.x
并不存在所以为 undefined
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