var aa = {a: 1};
var bb = aa;
bb = {};
console.log(aa); // {a: 1}
var aa = {a: 1};
var bb = aa;
bb.a = 2;
console.log(aa); // {a: 2}
有些不解, 为什么第一段代码的aa不是{}, 遇见{}就会重新在堆中建立一个新内容吗?
顺便问下利用这种特性, 有哪些衍生的奇淫巧技?
高级编程3中4.1.3中关于函数参数传递的部分解释的好像有误啊, 如果按照大家给出的答案, 不知道是不是翻译错了, 书里用参数是值传递来解释上面的问题(其实书里关于这里的描述有一段本身就有语病, 不知道是不是翻译错了?)
{}
相当于一个新的对象,而bb = {}
相当于修改了 bb 的指向地址。所以现在
b和a不指向同一堆内存
了,bb 只是一个指向另一个对象的指针。aa是不变的。
第二个中,
bb.a
修改了内存的内容,此时 bb 和 aa 还是指向同一内存的,所以修改bb.a后 aa.a 也会修改。这个方面应用还是挺多的,不好的地方也挺多。
比如使用原型构造对象(并非纯粹的原型构造),其中属性定义在对象上,而方法定义在对象的原型上。
每次实例化的对象,他们的方法不会发生拷贝(属性会进行拷贝),省很多内存。但是随之而来的也会存在问题,比如一个对象修改了原型的内容,则其他的所有对象都会随之一起修改。
比如 vue2.0中,子组件不允许修改父组件的值,但是传递引用过去之后,通过修改对象的属性,就可以实现修改父组件的值。(对象的引用是不会变的,就想上面,aa没变化,但是aa.a变化了)
这样的应用还很多。
这本书有些地方翻译的不是很好,有些生硬。当时我看这本书的时候这部分也比较疑惑。
其让人费解的部分其实就是他对下面的解释
我个人的理解是,函数参数是对象(表面上看是一个对象)的时候,比如
obj
,obj 他的确是和person指向同一个堆内存,因此第一个修改是一样的。而实际上person是一个
指针
,而obj也是一个指针类型
(我不确定在javascript中描述指针是否正确),如果你接触c
比较多的话就能够明白。person和obj也可以理解为特殊的变量,因此他们也有值。本身指针也可以重新赋值。因此,当上面的函数中obj被重新赋值之后,指向的内容就不同了。这就充分说明,obj实际上就是一个指针变量,传递过来的是指针变量的值(这个值的概念我也不确定这样描述是否有问题).