JavaScript高级程序设计-第3版-中 有这么一段话:
在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的①。
① 这种说法不严密,当复制保存着对象的某个变量时,操作的是对象的引用。但在为对象添加属性时,操作的是实际的对象。
这里的重点是①的注释,初次看的时候没有理解,后来理解了,举个例子:
先看①的前半句,比较好理解:
当复制保存着对象的某个变量时,操作的是对象的引用。
var a = { n: 2 }; //这里把 { n: 2 } 赋值给 a,实际上是把 a 的指针指向 { n: 2 } var b = a; //这里把 a 赋值给 b,实际上是把 b 的指针指向 a 的指针,最终是把 b 的指针指向上一个对象{ n: 2 }; var c = { n: 2 }; //这里把 { n: 2 } 赋值给 c,实际上是把 c 的指针指向 { n: 2 } ,但是这个对象和前面的对象不等,只有指针指向同一个对象时,两个对象才相等; console.log(b); //{ n: 2 } console.log(a === b); //true,b 保存是指针,a 也是,两个指针指向同一个对象,所以相等,所以 a,b 保存的都是同一个对象的引用 console.log(a === c); //false ,a,c 看起来相等,实际上是两个指针指向不同的对象;彼此没有发生引用关系;
这里还没有涉及到 ①的后半句:
但在为对象添加属性时,操作的是实际的对象。
这句话用来解释下面问题就很有用了:
var a = { n: 2 }; var b = a; a.x = 1; // 操作的是对象 a 的引用还是实际对象 { n: 2 }? console.log(a); // { n: 2, x: 1 } console.log(b); // { n: 2, x: 1 }
如果按书上原话,操作的是对象 a 的引用,那这里就是把 a 由指向 { n: 2 } 转为 指向 { n: 2, x: 1 },如果这个逻辑是正确的,那么 b 应该还是 { n: 2 } ,然而事实不是,证明这个逻辑不对;
如果按照①的逻辑,操作的是实际的对象,那这里就是把 { n: 2 } 这个对象变成了 { n: 2, x: 1 },而 a,b 本身就指向的这个对象,所以 a,b 的输出自然就是 { n: 2, x: 1 },逻辑正确。
所以,当复制保存着对象的某个变量时,操作的是对象的引用。但在为对象添加属性时,操作的是实际的对象。
参考资料: