直奔主题,先贴上代码:
let a = {n:1}
a.x = a = {n:2}
console.log(a.x)
console.log(a.x)
输出什么呢?
作为一个初学者,我的第一反应还是挺懵的,尤其是对于a.x = a = {n:2}
这一句,非常地不理解。
于是,我去查了一些资料,并且不断尝试修改代码,经过一系列折腾之后,我终于搞懂了,觉得这题可真有意思。按捺不住内心的开心与激动,想借此机会把我对于这段代码的理解,赶紧记录下来。一来是方便以后自己查看,同时也希望能帮到同样搞不明白的你们。
这段代码,主要是涉及了两个知识点:
- 引用类型的数据是如何存储,变量是如何指向的?
- JS 中表达式的执行顺序是从左往右
接下来,我将详细地解析一下这段代码,到底发生了什么。看完本文,我相信,你一定能够明白这道题目是咋回事了。
首先,为了能更好地理解这段代码中变量 a
所指向的对象的变化(由原来的{n: 1}
变成了{n: 2}
),现在引入一个变量 b
,让 b
和 a
指向同一个对象。
代码如下:
let a = {n:1}
let b = a
a.x = a = {n:2}
console.log(a)
console.log(b)
为了更直观地理解,当执行完第二行后,它们的指向关系可以用下图表示:
注意,let b = a
代表的是把变量a
的值,赋值给变量b
,而变量a
的值是啥?有一点JS基础的同学都知道,a变量存储的并不是对象{n: 1}
,而是指向对象{n: 1}
的一个指针
,也就是一个内存地址
。
于是呢,变量b和变量a 存储的都是同一个地址,那么它俩自然就是指向同一块内存空间,也就是a 和 b 都指向{n: 1}
,正如上图中画的那样。
到目前为止,理解起来都不难。
但,下面这句,就不太好理解了:
a.x = a = {n:2}
首先,对于这句代码,我们应该先明白一件事,就是 JS 的表达式是从左往右执行的。
好,那既然是从左往右执行,那我们就一点一点来呗,把这行代码进行一下拆分,
将a.x = a = {n:2}
拆分成 a.x =
和 a = {n:2}
接下来就是本文的重点了!我对拆分后的理解是这样的:
首先,执行到 a.x =
时,可以理解为,我们想要给a
所指向的对象添加一个x属性
,但是属性x
的值是什么呢?就应该是a.x =
后面代码返回的值。
好,先就此打住,我们先不管后面返回的值是啥,就目前的状态,是不是可以用下面这张图去描述:
我们想要给 a.x
赋值,但是现在还不知道值是什么。
那么,接下来我们再来看看拆分的后半段代码a = {n: 2}
做了什么,返回的又是什么。
重点中的重点! a = {n: 2}
,做了什么
?又返回了什么
?
- 做了什么?
a = {n: 2}
,就是让 a 这个变量,指向一个新的对象{n: 2}
,注意,不是之前那个和b共同指向的对象了哦! - 返回了什么?
a = {n: 2}
的返回值,我们可以通过console.log(a = {n: 2})
查看,返回的是{n: 2}
,所以这个返回值{n: 2}
会赋值给变量 x
于是,综合上面两点, a 和 b 的指向就变成了下图:
好,到此为止,问题就分析完了,再回到最初的那段代码:
let a = {n:1}
a.x = a = {n:2}
console.log(a.x)
现在再来回答 a.x
是啥?是不是就很清晰了,a所指向的对象里压根就没有 x,所以打印结果就是 undefined
最后,贴上控制台打印的截图,来验证上面画的 a 和 b 的指向:
以上就是我对 JS 中 a.x = a = {} 到底发生了啥
的理解,希望有帮到你。
如有错误之处,还望及时指正,欢迎交流探讨!😄