资讯专栏INFORMATION COLUMN

JavaScript之浅、深拷贝

leanxi / 1489人阅读

摘要:前言里面浅拷贝和深拷贝是非常关键的知识点,今天就来通过本文清楚的了解深浅拷贝以及该如何实现这两种拷贝方式。对象的拷贝又分为浅拷贝和深拷贝。印证了上述所说的对于所有的基本类型,简单的赋值已经是实现了深拷贝。

前言

JavaScript里面浅拷贝和深拷贝是非常关键的知识点,今天就来通过本文清楚的了解深浅拷贝以及该如何实现这两种拷贝方式。

深浅拷贝的区别

拷贝:其实就是一个对象复制给另外一整个对象,让对象相互不影响。对象的拷贝又分为浅拷贝和深拷贝。

对象的浅拷贝(只拷贝一层),所谓的浅拷贝,只是拷贝了基本类型的数据,对于引用的类型数据,复制后也是会发生引用,这种拷贝就叫做浅拷贝。

对象的深拷贝(拷贝多层),要求要复制一个复杂的对象,这就可以利用递归的思想来实现,省性能又不会发生引用,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。

浅拷贝和深拷贝只针对object这样的复杂的对象而深拷贝,因为对于所有的基本类型,简单的赋值已经是实现了深拷贝。

例子1.首先来让我们思考一下以下的 a 应该是多少?

显而易见,a 是1。印证了上述所说的对于所有的基本类型,简单的赋值已经是实现了深拷贝。我们可以简单地理解,这种b变了不影响a的就叫做深拷贝。

例子2.那么在这种情况下,a.name 又是多少呢?
*以下44为假设,下同。

很明显,a.name 是"b"。同样我们可以简单地理解,这种b变了影响a的就叫做浅拷贝。

在例子2中,为什么 b 改变了会影响 a 呢?因为我们仅仅是把堆里所记录的地址44复制给了 b ,所以在后来我们对 b.name 修改时,会对44里记录的 name 直接修改,当 a 再去引用的时候已经是被修改过的44了。


我们想要在修改时候两者互不影响,应该是要像上图一样,创建一个新地址55,里面所包含的内容和地址44一样,这样在修改时才会互不影响。同样如果引用里还有引用,也要做到内容一样地址不一样,只有两者引用互无关联才能做到互不影响,才能实现了深拷贝。

如何实现深浅拷贝?

在了解了深浅拷贝的区别之后,我们想要实现深浅拷贝的话该怎么办呢?

浅拷贝

1.ES6:object.assign()

var target = {a: 1, b: 1};
var copy1 = {a: 2, b: 2, c: {ca: 21, cb: 22, cc: 23}};
var copy2 = {c: {ca: 31, cb: 32, cd: 34}};
var result = Object.assign(target, copy1, copy2);
console.log(target);    // {a: 2, b: 2, c: {ca: 31, cb: 32, cc: 33}}
console.log(target === result);    // true

深拷贝

1.JSON.parse() 和 JSON.stringify()

var target = {a: 1, b: 1, c: {ca: 11, cb: 12, cc: 13}};
var targetCopy = JSON.parse(JSON.stringify(target));
targetCopy.a = 2;
targetCopy.c.ca = 21;
console.log(target);   // {a: 1, b: 1, c: {ca: 11, cb: 12, cc: 13}}
console.log(targetCopy);    // {a: 2, b: 1, c: {ca: 21, cb: 12, cc: 13}}
console.log(target === targetCopy);  // false

可以看出通过JSON.parse() 和 JSON.stringify()我们可以很简单的实现了深拷贝,但是值得注意的是,JSON.parse() 和 JSON.stringify() 能正确处理的对象只有 Number、String、Array 等能够被 json 表示的数据结构,因此函数、Date等这种不能被 json 表示的类型将不能被正确处理。

2.判断类型 + 递归拷贝(不可能复制__proto__)

function clone(object){
    var object2
    if(!(object instanceof Object)){
        return object
    }else if(object instanceof Array){
        object = []
    }else if(object instanceof Function){
        object = eval(object.toString())
    }else if(object instanceof Object){
        object = {}
    }
    for(let key in object){
        object2[key] = clone(object[key])
    }
    return object2
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106502.html

相关文章

  • 小tips:JS之浅拷贝拷贝

    摘要:浅拷贝深拷贝浅拷贝的问题如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。 浅拷贝: function extendCopy(p) {  var c = {};  for (var i in p) {    c[i] = p[i];  }  return c; } 深拷贝: function deepCopy(p...

    Soarkey 评论0 收藏0
  • Js之浅拷贝拷贝与对象数组的遍历

    摘要:判断是深拷贝对象还是数组如果要拷贝的对象的属性依然是个复合类型,递归运用递归,当要拷贝的对象或者数组的属性依然是个对象或者数组时,递归调用。遍历对象聊完了深拷贝和浅拷贝,接下来说一下遍历。 在js这门语言中,数据存放在堆中,而数据的引用的存放在栈中。 浅拷贝 我们说的浅拷贝,指的是,引用地址的拷贝,栈中两块不同的引用地址都指向了堆中同样一块区域。所以,我们通过一个地址修改了堆中的数据,...

    liangzai_cool 评论0 收藏0
  • Javascript系列之浅复制与复制

    摘要:定义浅复制如果复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响。浅复制数组浅复制利用数组方法和返回新数组特性,进行复制。深复制对象深复制利用对象的和方法。 定义 浅复制 如果复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响。 深复制 深复制不是简单的复制引用,而是在堆中重新分配内存,并且把源对象实例的所有属性都进行新建复制,以保证深复制的...

    MonoLog 评论0 收藏0
  • JS系列之目录

    摘要:设计模式资源整理操作符小知识点实现发邮件功能数据结构与算法资源整理跨域函数的合成与柯里化系列之防抖节流系列之正则系列之系列之系列之编码系列之系列之操作符对象中的坐标检测对象或数组系列之机制系列之构造对象系列之总结系列之浅复制与深复制系列之对 Javascript设计模式资源整理JS操作符JS小知识点JS实现发邮件功能数据结构与算法资源整理跨域函数的合成与柯里化JS系列之防抖节流JS系列...

    AaronYuan 评论0 收藏0
  • JavaScript中的浅拷贝拷贝

    摘要:所以,深拷贝是对对象以及对象的所有子对象进行拷贝实现方式就是递归调用浅拷贝对于深拷贝的对象,改变源对象不会对得到的对象有影响。 上一篇 JavaScript中的继承 前言 文章开始之前,让我们先思考一下这几个问题: 为什么会有浅拷贝与深拷贝 什么是浅拷贝与深拷贝 如何实现浅拷贝与深拷贝 好了,问题出来了,那么下面就让我们带着这几个问题去探究一下吧! 如果文章中有出现纰漏、错误之处...

    AZmake 评论0 收藏0

发表评论

0条评论

leanxi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<