深入理解对象的引用

作者: 小红依 | 来源:发表于2017-11-15 20:39 被阅读32次

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

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

相关文章

  • 深入理解对象的引用

    首先我们来讲一下赋值关系和引用关系 赋值关系 a和b是简单的赋值关系,这种赋值关系存在于基本类型中 对于函数和对象...

  • 深入JVM对象引用

    在jdk 1.2以前,创建的对象只有处在可触及(reachaable)状态下,才能被程序所以使用,垃圾回收器一旦发...

  • 深入理解C++中的对象和对象引用

    转载有言在先: 返回局部对象和引用, 就像返回局部变量的地址一样, 非常非常危险, 要避免使用。 下面程序中有的...

  • JVM的垃圾收集器策略

    说明:本篇属于读书笔记,大量参考《深入理解Java虚拟机》 判断对象不可用的几种方式 引用计数量法 通过计算对象被...

  • iOS 内存泄漏之循环引用

    何为循环引用?简单理解:对象A强引用B,对象B也强引用A; 何时会发生循环引用?使用delegate、block的...

  • iOS开发之进阶篇(8)—— Run Loops

    引用 Apple文档 -- Run Loops深入理解RunLoopiOS刨根问底-深入理解RunLoop 首先感...

  • iOS开发循环引用

    一、循环引用的产生 1.说明 -- :表示弱引用。 -> :表示强引用。 循环引用可以简单理解为对象A引用了对象B...

  • JVM对象引用与内存分配策略

    我的CSDN博客同步发布:JVM对象引用与内存分配策略 前两天对《深入理解虚拟机》一书做了个总结:《JVM理解其实...

  • JVM(三) -- JVM对象回收判断

    主要来源自阅读深入理解java虚拟机 引用计数法 对对象添加一个引用计数器,每当有一个地方引用,计数器就会加1;当...

  • 深入理解引用与引用传递

    1.引用的本质 比如示例代码: 该代码内存及引用创建过程 (1) 在堆内存创建object对象,对象地址为40f1...

网友评论

    本文标题:深入理解对象的引用

    本文链接:https://www.haomeiwen.com/subject/luwhvxtx.html