一道周爱民老师的御用面试题,考查js基础

304 阅读2分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。

题目

let a = { n: 1 }
a.x = a = { n: 2 }

console.log('a.x :>> ', a.x)

看到这种八股文面试题我就头大,考查这些东西有意思吗?

算了,{ n:1 } 或者 { n:2 },随便猜一个吧。

答案:

image.png

fxxk!我就知道,js 真的不讲武德!

算了,把 a 也打印出来看一下,分析一下吧。

let a = { n: 1 }
a.x = a = { n: 2 }

console.log('a.x :>> ', a.x)
console.log('a :>> ', a)

image.png

等一下,我好像明白了什么,这不就是 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)

image.png

果然如此,如今的 a 已经指向了新的地址,以前的 a(prevA) 则是不受影响,上面的 n 属性还是 1。

但是为啥 prevA 上的 x 属性为 { n: 2 } 呢?

而且题中连续赋值的写法,也是相当令人困惑:

a.x = a = { n: 2 }

这里我也是一知半解,知道运算符优先级之后才豁然开朗。

运算符优先级

mdn 上查了一下:

image.png

image.png

. 运算符优先级为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,内存空间分布如下:

image.png

然后,把 a 赋值给 prevA,其实就是它们俩指向同一个内存地址。

image.png

然后,给 a 添加属性 x, prevA 和 a 指向同一内存地址,也会被添加上 x 属性。

image.png

最后,a 指向了新的内存地址,a 和 prevA 从此分道扬镳。

image.png

小结

本题考查了:

  • 引用类型赋值问题
  • 运算符优先级和表达式执行顺序问题

以后谁再说 js 比其他编程语言简单的,请打死他!