今天群里面讨论了一个小问题
var a = {n:1}
var b = a
a.x = a = {n:2}
console.log(a.x) // ?
console.log(b.x) // ?
一开始我的想法是
// 按赋值运算符优先级
a = {n:2}
a.x = {n:2}
// b指向a的值
// a.x {n:2}
// b.x {n:2}
正确答案是:
console.log(a.x) // undefined
console.log(b.x) // {n:2}
为什么会是这个答案呢?
首先,需要了解的是,js变量赋值,传递的不是变量的标识符地址,而是变量的值。基本类型(字符串、数字、布尔类型)进行值的复制,引用类型(对象)进行值的地址的引用。
var aString = 'abc'
var bString = aString // 值拷贝
var aObj = {n:1}
var bObj = aObj // 变量bObj 指向aObj 的值 : {n:1}
aObj.a = 1 // aObj 的值为 {n:1,a:1}
console.log(bObj) // {n:1,a:1}
aObj = {c:1} // aObj 的值为 {c:1}
console.log(bObj) // {n:1,a:1}
// 值是复杂类型时,变量赋值是值的地址的拷贝
回到前面的问题,
var a = {n:1}
var b = a // b指向对象{n:1}
// 这里是重点
a.x = a = {n:2}
// a = {n:2} 使a指向对象{n:2}
// 但同一行内连续赋值的话
// 最前面的a.x 的a 并没有因为 后面的 a = {n:2} 改变指向
// 而是仍指向{n:1} 这个对象
// 因此
console.log(a.x) // a 指向了 {n:2} 此时a没有属性x 所以undefined
console.log(b.x) // b 仍指向 {n:1} 而由于前面的a.x操作为它创建了属性x = {n:2}
// 因此结果是{n:2}
这题重点有两个,一个是变量赋值的操作,另一个是当连续等号赋值操作时,变量对应的值与分开写的区别。
方方老师点评:去了解编译原理,这跟js关系不大
23333