• 深入理解对象的引用


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

    • 赋值关系
    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主要是因为经常在网上看一些文章,有问题想问作者又得不到作者即使的回复,让人很懊恼,虽然我的文章并不会被很多人看到,但我要对看到我文章的人负责。

  • 相关阅读:
    最长上升子序列
    盒子与小球之三
    盒子与小球之二
    《深入理解计算机网络》读后小记 2
    《深入理解计算机网络》读后小记 1
    想成为Java高手的25个学习目标
    POI中设置Excel单元格格式
    如何用jar命令对java工程进行打包
    【网络流】有源汇上下界最大流
    【网络流】网络流基本概念
  • 原文地址:https://www.cnblogs.com/huyuzhu/p/7840858.html
Copyright © 2020-2023  润新知