前言
群里看到有人发出的问题,觉得有价值,记录一下。
先贴代码
打开控制台,将代码执行。
let a = {n: 1}
let b = a
a.x = a = {n: 2}
console.log(a.x) // ?{n: 2}
console.log(b.x) // ?{n: 2}
分析
估计大伙一眼看去直接就是a.x={n: 2},b.x={n: 2}了吧~
JS 引擎在执行赋值语句时,会先从左往右解析各个变量名,转换成变量值,然后从右往左执行赋值。
-
先解析,在
a.x = a = {n: 2}中,a.x的实际值是{n: 1}.x,a的实际值是对象{n: 1}的引用地址 -
再赋值,从右往左进行赋值操作,遇到第一个
=,a实际值修改为对象{n: 2}的引用地址,遇到第二个=,此时a已经指向{n: 2},所以真实操作是令{n: 1}.x={n: 2}即{n: 1,x: {n: 2}}; -
此时只省变量
b还保持着原来对象{ n:1 }的引用地址,只不过添加新成员x,变成了{n: 1, x: {n: 2}}了; -
变量
a的实际值已经改为 对象{n: 2},所以a.x = undefined。(辅助理解:如果使用const关键字声明a,则会抛错,提示重复声明。) -
所以
let a = {n: 1}
let b = a
a.x = a = {n: 2}
console.log(a.x) // {n: 2}
console.log(b.x) // undefined