最近在回顾《Javascript高级程序设计》这本书的 “基本类型和引用类型的值” 时,对
基本类型值的传递如同基本类型变量的复制一样;引用类型值的传递如同引用类型变量的复制一样 。
访问变量有按值和按引用两种方式,而参数只能按值传递。
不太理解,百度了很多资料并且整理了自己的思路以后,想把自己的思考记录下来。
由于基本类型变量的访问、复制和参数传递都比较容易理解,所以本文只针对引用类型变量来阐述我的理解。前端小白,如果有错劳烦指出,愿意悉心接受教导,勿喷(求生欲)。
情景想象:
首先,假设有甲、乙两个人,他们分别处在不同的位置(类比于不同变量存储在内存的不同地址),以及一个房子(引用类型),房子的地址被记录在一张纸上,并且只有甲拿到这张纸。
1. 按引用访问
甲知道房子的位置,根据自己的位置和房子的地址生成了一条路线(引用),按照这条路线(引用)甲成功找到了房子,并且获取了房子的各种属性。
2. 按值复制
此时,乙也想访问房子,于是甲把手中的地址复制了一份给了乙,乙根据自己的位置和房子的地址生成了一条新的路线(新的引用)。
当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。
这个值就是房子的地址,甲将地址复制一份放到了乙的手中,两人通过不同的路线(引用)访问到同一所房子(引用类型),若乙对房子进行装修、扩充或缩小(修改、增加或删除属性),那么甲看到的房子也会产生相应的变化(甲访问到的属性会随着乙的操作进行变化)。
如果是按照引用复制,那么甲应该是将自己的路线复制给了乙,因此甲和乙只能走同一条路线(引用),反推此时甲和乙是在同一个位置,即甲和乙只能是同一个人(变量),这种情况显然不成立。
3. 按值传递
按值传递跟复制是一样的原理,如果能理解按值复制,那么按值传递也不难理解。因此这里我只解释以下的代码。
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Grey";
}
var person = new Object();
setName(person);
alert(person.name); // "Nicholas"
在 obj = new Object() 执行前,person 和 obj 指向同一个引用类型。
因此 obj 对引用类型的修改在函数外部的 person 也有所反映。而在执行 obj = new Object() 后,此时的内存分配变为
obj 的指针被修改了,obj 的引用指向了新的引用类型,person 的引用跟 obj 的引用不同,因此 person 的指向不会改变,仍然指向原来的引用类型,此时 obj 修改引用类型的属性,person 指向的引用类型没有改变。