深入理解对象的引用

首先我们来讲一下赋值关系和引用关系

  • 赋值关系
var a = 5;
var b =a;
b+ = 3;
alert(b);//8
alert(a);//5

a和b是简单的赋值关系,这种赋值关系存在于基本类型中

  • 对于函数和对象,存在的不是简单的赋值关系,而是引用关系

我们来看两种情况

var a = [1,2,3]
var b = a;
b.push(4);
alert(a)//1,2,3,4
alert(b)//1,2,3,4

在这种情况下,a和b共用一个内存空间。就像我们c语言中的指针。用一种更形象的说法:a与b都有一个存库的门,所以他们都能改变这个仓库,都改变的是同一个仓库。

var a = [1,2,3];
var b = a;
b = [1,2,3,4];
alert(a)//1,2,3
alert(b)//1,2,3,4

这种情况就和刚才有点不同了。你或许会想,ab不是共用一个内存吗,为什么b变了a不跟着变。
在这里我们就要注意这两句的区别了

b.push(4);
b = [1,2,3,4];

前面一句是用数组方法向仓库里放了一个4,所以ab呈现出来的都是1234毕竟他们用的是一个仓库。而后面一句b = [1,2,3,4];而是创建了一个新数组,重新放入1,2,3,4,这时候他已经和a没有关系了,他放入的前三个数甚至可以不是和a一样的123了。

我觉得这两个例子就像这样的一个故事:a和b是一对父子,小时候b和爸爸a一起生活,有时为家里添置一点小家具;后来b长大了就自己买房子了,自己可以把房子装修得完全不一样了。(个人理解,帮助记忆而已,不必深究)

了解了对象的引用关系,下面我们来谈谈怎样复制对象

对象的拷贝有两种方式,我们称为深拷贝和浅拷贝,浅拷贝就是只复制最表面的那一层对象,我们来看下面这个例子

var obj = {
	a:10
}
function copy() {//浅拷贝
	var newObj = {};
	for(var attr in obj) {
		newObj[attr] = obj[attr];
	}
	return newObj;
}

var obj2 = copy(obj);
obj2.a = 20;
alert(obj.a)//10

在这个例子中,我定义了一个拷贝的函数,这个函数的思路是:把所有a中的属性都复制到b中去,然后返回一个新对象。因为obj对象中只有一层,所以obj2拷贝成功。

我们再来看看原对象不止一层的情况

var objX = {
	a:{b:10}
}
var objY = copy(objX);
objy.a.b = 20;
alert(objX.a.b)//20 复制失败

这里我们还是使用的上面的拷贝函数。我们可以看到,这一次就拷贝失败了。这就是我说的浅拷贝这能拷贝一层对象。

下面我们来看深拷贝

深拷贝其实拷贝的原理和浅拷贝是一样的,我们需要做到的就是把每一层对象都拷贝过去。这里我采用递归的方法。

递归应该大家都知道,到可能概念模模糊糊,所以我先简单的介绍一下递归。

  • 递归

递:传递

归:回到之前的位置

image.png
我们来看一个求阶层的例子

function test(n) {
	return n*test(n-1);
}

我们要在它返回的时候再去执行它本身,每次传进的参数会小1.当然,这传递的运算必须要有一个结束的时候,所以我们要进行判断什么时候结束

function test(n) {
	if(n==1) {
		return 1;
	}
	return n*test(n-1);
}

这里在n=1时函数就执行结束了。

所以总结递归的两个点

  1. 函数调用函数自身,执行递的动作
  2. 最后一次判断一个终止条件,可以执行的动作

然后我们的深拷贝就开始了

function deepCopy(obj) {
	if(typeof obj != 'object') {
		return obj;
	}
	var newObj = {};
	for(var attr in obj) {
		newObj[attr] = deepCopy(obj[attr]);
	}
	return newObj;
}

在这里,我们一层一层的往下剥,剥到不是对象的时候就停止了,也就实现了深拷贝

如果你对我的文章有想说的话,欢迎qq交流:425910502.在这里附上qq主要是因为经常在网上看一些文章,有问题想问作者又得不到作者即使的回复,让人很懊恼,虽然我的文章并不会被很多人看到,但我要对看到我文章的人负责。

posted @ 2017-11-15 20:41  叫我小红依吧  阅读(255)  评论(0编辑  收藏  举报