昨晚在对象值引用的问题了花了2小时,今天爬起来看权威指南和MDN,终于总结出来了(虽然网上已经很多了,但不是自己经历还是不够深刻)
以下是简单化的问题:
//定义obj对象,里面有一个object类型的a属性
var obj ={
a:{}
};
// 定义 v1,2,3值是object
var v1 = {v:'1'};
var v2 = {v:'2'};
var v3 = {v:'3'};
// 定义一个Array
var arr = new Array();
//v1,2,3分别赋值给obj.a 每次赋值后将obj push进array
obj.a = v1;
arr.push(obj);
obj.a = v2;
arr.push(obj);
obj.a = v3;
arr.push(obj);
console.log(arr)
//输出arr数组里面3个object对象里面的a都等于{v:'3'}
//下面变化一下
//v1,2,3分别赋值给obj.a 每次赋值后将obj.a push进array
obj.a = v1;
arr.push(obj.a);
obj.a = v2;
arr.push(obj.a);
obj.a = v3;
arr.push(obj.a);
console.log(arr)
//输出arr数组里面3个object对象里面的a分别等于
//{v:'1'}{v:'2'}{v:'3'}
以上是对象值赋值遇到的问题,根据JavaScript权威指南第三章3.7(不可变的原始值和可变的对象引用)的解释:
JavaScript的原始值(undefined,null,boolean,number,string)
和
JavaScript的对象(Function,Array,Object)的赋值有根本区别
前者的赋值不可改变,后者的赋值等于引用等号右边的值的地址,术语叫对象值的引用。
比如:
//为创建一个 内存A 地址(值为1),a指向这个内存A
var a = ['1'];
//这句实际上b指向了a,而a指向内存A,所以b也指向内存A
var b = a;
//为创建一个 内存C 地址(值为2),c指向这个内存C
var c = ['2'];
//b = c将b的指向从内存A改为内存C,此时输出a,a访问内存A获值,等于1
b = c;//console.log(a) -> ['1']
/**
*b[0] = c 与b=c不同 b[0]是直接修改内存的值,
*这里是修改内存A的值,所以内存A的值被修改成了内存C的值,
*此时输出a,a访问内存A获值,等于2
**/
b[0] = c;//console.log(a) -> ['2']
这样可以解释第一个例子,因为arr.push(obj)时候,
obj.a的3次引用v1,v2,v3并没有改变obj的引用地址,
只是改变了obj.a的引用地址,
所以arr[0] arr[1] arr[2] 引用obj, obj引用obj.a,所以arr数组的值以最后obj.a的值为准
而arr.push(obj.a)的时候,obj.a经过3次引用地址的改变,
所以
arr[0]指向v1地址
arr[1]指向v2地址
arr[2]指向v3地址
如果需要改变arr的值,只要v1.v =”改变arr的值” 就可以了。
以上是我对象引用的总结。。