「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
题目
let a = { n: 1 }
a.x = a = { n: 2 }
console.log('a.x :>> ', a.x)
看到这种八股文面试题我就头大,考查这些东西有意思吗?
算了,{ n:1 } 或者 { n:2 },随便猜一个吧。
答案:
fxxk!我就知道,js 真的不讲武德!
算了,把 a 也打印出来看一下,分析一下吧。
let a = { n: 1 }
a.x = a = { n: 2 }
console.log('a.x :>> ', a.x)
console.log('a :>> ', a)
等一下,我好像明白了什么,这不就是 js引用类型的赋值问题吗?
a 被一个新的对象赋值,指向了一个新的地址,以前的地址就没用了,所以 a.x 是undefined。
用一个 prevA 来记录 a 以前的地址,再试一下:
let a = { n: 1 }
const prevA = a
a.x = a = { n: 2 }
console.log('a.x :>> ', a.x)
console.log('a :>> ', a)
console.log('prevA :>> ', prevA)
果然如此,如今的 a 已经指向了新的地址,以前的 a(prevA) 则是不受影响,上面的 n 属性还是 1。
但是为啥 prevA 上的 x 属性为 { n: 2 } 呢?
而且题中连续赋值的写法,也是相当令人困惑:
a.x = a = { n: 2 }
这里我也是一知半解,知道运算符优先级之后才豁然开朗。
运算符优先级
去 mdn 上查了一下:
. 运算符优先级为18,且表达式执行顺序为从左向右;
= 运算符优先级为2,且表达式执行顺序为从右向左。
优先级越大,越先执行,所以:
a.x = a = { n: 2 }
其实就相当于:
a.x = { n: 2 }
a = { n: 2 }
所以,我们画个图来总结一下整体的流程:
let a = { n: 1 }
const prevA = a
a.x = { n: 2 }
a = { n: 2 }
首先,定义一个引用类型指向a,内存空间分布如下:
然后,把 a 赋值给 prevA,其实就是它们俩指向同一个内存地址。
然后,给 a 添加属性 x, prevA 和 a 指向同一内存地址,也会被添加上 x 属性。
最后,a 指向了新的内存地址,a 和 prevA 从此分道扬镳。
小结
本题考查了:
- 引用类型赋值问题
- 运算符优先级和表达式执行顺序问题
以后谁再说 js 比其他编程语言简单的,请打死他!