本次文章主要对于下面这道经典面试题做一个解析:
let a = { n: 1 }; let b = a; a.x = a = { n: 2 }; console.log(a.x);//=>undefined console.log(b);//=>n: 1 x:n: 2错误思路一:将{ n: 2 }赋值给a,然后再将{ n: 2 }赋值给a.x。
错误思路二:将{ n: 2 }先赋值给a.x,然后在把{ n: 2 }赋值给a。
排雷
有些知识点不明白我们的思路就会陷入雷区,怎么都是错的,所以我们首先要排雷
在这里需要我们先了解一下=的赋值过程,是从右到左一次赋值,将{ n: 2 }赋值给a,然后再将{ n: 2 }赋值给a.x,说道这里有的朋友可能要问了,那为什么第一种思路是错误的呢?
那么我们需要说说js中的运算符优先级问题啦,在js中‘.’的优先级为19,从左到右,而等号的优先级为3,从右到左。数字越大,优先级越高谁就先执行。
关于js运算符更加详细的内容可以参考developer.mozilla.org/zh-CN/docs/…
下面是正解思路:
第一步我们定义了一个对象a,然后定义了一个对象b,将a的值赋给b,这里是引用数据类型赋值和普通数据类型的区别,如果引用数据类型已经被创建,则赋值过程是将a的内存地址赋给b,如果是新创建的一个对象,我们需要另外开辟一个堆内存空间,然后将新的内存地址赋值给b。普通数据类型是另外创建一个值。

第二步 a.x = a = { n: 2 }详细过程:
在赋值的过程中主要有以下三个步骤,
1.开辟内存空间将{n:2}这个对象以字符串的形式存储在堆内存中(重新开辟一个内存空间存储{n:2},假如为0x0002)
2.定义变量名(a.x和a此时都对应0x001这个内存地址)
3.执行赋值操作(将0x0002赋值给a,失去引用的内存地址将会被浏览器在特定时间消除,但是我们此时还有b在指向0x0001地址,所以不会被浏览器回收,然后将0x0002的地址赋值给a.x开辟的引用地址,这在第一步已经确定。其实这个操作是将0x0002的地址赋值给b.x,因为a的引用地址已经改变)