js中的浅拷贝与深拷贝,只是针对复杂数据类型(object, Array)的复制问题。浅拷贝和深拷贝都可以实现在已有对象上再生出一份的作用。但是对象的实例是存储在堆内存中然后通过一个引用值只操作对象,由此拷贝的时候存在两种情况:拷贝引用和拷贝实例,也就是咱们今天要讨论的浅拷贝和深拷贝。


  • 浅拷贝 : 浅拷贝是拷贝引用,拷贝后的引用都是指向同一个对象实例,彼此之间操作都会有影响
  • 深拷贝 :在堆中重新分配内存,并且把源对象所有属性都进行进行新建拷贝,以保证深拷贝的对象的引用图不包含任何原对象上的对象引用图上的任何对象,拷贝后的对象原对象完全隔离互不影响。

浅拷贝

浅拷贝分两种情况,拷贝直接拷贝源对象的引用和源对象拷贝实例,但其属性拷贝引用

拷贝原的引用

这是最简单的浅拷贝。例:

let a = {c:1};
let b = a;
console.log(a === b) //true
a.c = 2
console.log(b.c) // 2
复制代码

源对象拷贝实例,其属性对象拷贝引用

这种情况,外层源对象是拷贝实例,如果其属性元素为复杂数据类型时,内层元素拷贝引用。 对源对象直接操作,不影响两外一个对象,但是对其属性操作时,会改变两外一个对象的属性的只。 常用方法为:Array.prototype.slice(),Array.prototype.concat(), jQury$.extend({},obj),例:

let a = [{c: 1},{d: 2}];
let b = a.slice();
console.log(a === b) // false 说明外层数组拷贝的是实例
a[0].c = 3
console.log(b[0].c) // 3 说明其元素拷贝是引用
复制代码

深拷贝

深拷贝后,两个对象,包括其内部的元素互不干扰。常见方法有JSON.parse(),JSON.stringify(),jquery$.extend(true, {}, obj),lodash_.cloneDeep和_.clone(value, true)。例:

var a = {c: {d: 1}};
var b = $.extend(true, {}, a);
console.log(a === b); // 输出false
a.c.d = 3;
console.log(b.c.d); // 输出 1,没有改变。
复制代码

深拷贝就是增加一个“指针”,并申请一个新的内存,并且让这个新增加的“指针”指向这个新的内存地址,使用深拷贝,在释放内存的时候就不会像浅拷贝一样出现重复释放同一段内存的错误,当我们需要复制原对象而又不能修改元对象的时候,深拷贝就是一个,也是唯一的选择。我们来看一下例子

var arrayA = [ 1,2,3,4,5 ];
var arrayB = [] ;
arrayA.forEach ( function (element){arrayB.push(elemnt);
})
var str = 'hello'
arrayA.push(str) ;
console.log(arrayA);// [1, 2, 3, 4, 5, "abc"]
console.log(arrayB);// [1, 2, 3, 4, 5]
复制代码

这里的arrayA和arrayB中的最后一个元素,这个元素是一个对象,指向的是同一段内存地址,所以当修改其中一个元素对象的值时,导致了另一个的值也跟着发生改变,但是如果新增加的元素不是一个对象,而是一个字符串,或者一个数字,这时候是没问题的。有问题我们是需要去解决的,对于第一种情况,我们使用同样的方式去解决它。既然新增加的元素是一个字符串或者一个数字的情况下,改变一个元素的值不会引发另一个元素的值的改变,所以我们就使用这种方式去解决,解决方案如下所示:

function copy( sourceObj , c) {var c = c || ( Array.isArray(sourceObj) ? [ ] : {} );for (var i in sourceObj) {if (typeof sourceObj[i] === 'object') {c[i] = Array.isArray(sourceObj[i])  ? [] : {};copy (sourceObj[i], c[i]);} else {c[i] = sourceObj[i];}}return c;
}
var arrayA = [1,2,3,4,5];
var  obj = {name:'Alex'};
arrayA.push(obj)
var arrayB = [];
copy(arrayA,arrayB);
arrayB[5].name = 'Tom'
console.log(arrayA);// [1, 2, 3, 4, 5, "Alex"]
console.log(arrayB);// [1, 2, 3, 4, 5, "Tom"]
复制代码

我们先定义一个copy函数,传入两个参数,第一个参数是原对象,第二个参数是复制的对象,我们循环原对象,看原对象中的元素的类型是否是对象(Object),如果是的话我们再使用递归调用,copy这个对象,如果不是对象,直接赋值。最后返回copy后的对象,也就是这里的arrayB,当我们修改arrayB中的name的值时,arrayA里的值是不会跟着发生改变的。这里涉及到了递归调用,有不明白的童鞋可以看下递归相关的资料。这就完成了对一个对象的深拷贝。

浅拷贝比较容易理解,当然深拷贝也是容易理解的,只是得注意拷贝上面说的那种情况。就没问题了。有任何问题,欢迎提问

深入浅出的“深拷贝与浅拷贝”相关推荐

  1. 深入浅出解释深拷贝、浅拷贝、对象拷贝、引用拷贝原理和应用

    拷贝总体上分为引用拷贝和对象拷贝. 1. 引用拷贝 创建一个指向对象的引用变量的拷贝. public class QuoteCopy {public static void main(String[] ...

  2. 深入浅出深拷贝与浅拷贝

    一.基本类型与引用类型 ECMAScript 中数据类型可分为: 基本类型:String.Number.Boolean.Symbol.null.undefined 引用类型:Object.Array. ...

  3. Python 精选笔试面试习题—类继承、方法对象、包管理、闭包、可变类型作为默认参数、列表引用、sort与sorted、 append 和 extend、深拷贝和浅拷贝

    1. 类继承 如下代码 class A(object):def show(self):print 'This is calss A'class B(A):def show(self):print 'T ...

  4. C++深拷贝与浅拷贝

    浅拷贝就是成员数据之间的一一赋值:把值赋给一一赋给要拷贝的值.但是可能会有这样的情况:对象还包含资源,这里的资源可以值堆资源,或者一个文件..当 值拷贝的时候,两个对象就有用共同的资源,同时对资源可以 ...

  5. python的深拷贝与浅拷贝

    对于list, set, dict来说, 直接赋值. 其实是把内存地址交给变量. 并不是复制⼀份内容. 两个变量的内容其实为一个地址,如果要在复制的同时分配新的地址则需要用到深拷贝和浅拷贝的命令 ls ...

  6. 详谈Javascript中的深拷贝和浅拷贝

    数据复制是我们编程中经常会使用到的技术,对于普通数值数据来说,复制很简单,但是对于复杂类型比如对象的复制,就会有很多需要考虑的东西,比如我们经常说到的深拷贝和浅拷贝. 浅拷贝 复制的对象和原始对象属性 ...

  7. python怎么避免浅拷贝_详谈Python中的深拷贝和浅拷贝

    在平时工作中,经常涉及到数据的传递,在数据传递使用过程中,可能会发生数据被修改的问题.为了防止数据被修改,就需要在传递一个副本,即使副本被修改,也不会影响原数据的使用.为了生成这个副本,就产生了拷贝. ...

  8. c++深拷贝和浅拷贝

    C++中类的拷贝有两种:深拷贝,浅拷贝:当出现类的等号赋值时,即会调用拷贝函数 一:两个的区别 1 在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数--即浅拷贝,它能够完成成员的一一复制.当 ...

  9. 更清晰的认识对象——深拷贝与浅拷贝

    对象在引用的时候引用的是对象的地址,所以导致如果修改其中一个对象,就会对其他引用这个地址的对象进行修改,这种结果并不是我们想要的,这个时候我们就要用到深拷贝和浅拷贝去解决这个问题了. var a = ...

最新文章

  1. 我们是移动的韭菜么?似乎程序员去哪里上班,哪里房价就贵起来了?扎心......
  2. wireshark数据包分析实战
  3. POj 3420 Quad Tiling 状态压缩DP+递推+矩阵快速幂
  4. 创新品类,N次方的市场爆炸力
  5. groupby java_Java流-在GroupBy之后获取内部元素
  6. python学习之多线程多进程
  7. 转:孩子,上学去!乖
  8. ATTCK实战系列一(内网渗透入门)
  9. 使用近场探头和电流探头进行EMI干扰排查
  10. 太阳能无线充电系统设计
  11. ezw证件照芯片压缩算法
  12. #每日一题 力扣第22题 黑白格子画
  13. oracle表空间 online,表空间的ONLINE和OFFLINE状态
  14. c语言中0x11是多少,C语言中的符号
  15. .NET新手系列(九)
  16. OSChina 周日乱弹 —— 生活就像巧克力
  17. new和malloc区别
  18. 安装mysql数据库和mysql客户端
  19. 计算机的硬件系统和软件系统
  20. 【推荐】选品策略——新零售篇

热门文章

  1. UIMenuController的简单使用
  2. 基于CentOS中PXE网络环境构建实例
  3. XAML实例教程系列 - 命名空间(NameSpace)
  4. 自签名证书说明——自签名证书的Issuer和Subject是一样的。不安全的原因是:没有得到专业SSL证书颁发的机构的技术支持?比如使用不安全的1024位非对称密钥对,有效期设置很长等...
  5. brew 安装PHP的配置文件所在位置
  6. Pentaho Data Integration 界面开发
  7. BIND 子域授权的实现和区域转发实现
  8. RESTful Web Services初探
  9. Csharp: 拼音转汉字字符搜索字符串
  10. JNI开发篇——报错:Flag android.useDeprecatedNdk is no longer supported and will be removed in the next……...