javascript浅拷贝和深拷贝区别与实现

简介

注:浅拷贝和深拷贝都只针对于像Object, Array这样的复杂对象。
浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变。
深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变。
区别:浅拷贝只复制对象的第一层属性并不包括对象里面的引用类型数据、深拷贝是对对象以及对象的所有子对象进行拷贝

浅拷贝

1.实现浅拷贝的方法

(1)for...in只循环第一层

demo1.png

在上面的代码中,我们创建了一个 shallowCopy 函数,它接收一个参数也就是被拷贝的对象。

  • 首先创建了一个对象
  • 然后 for...in 循环传进去的对象,为了避免循环到原型上面会被遍历到的属性,使用 hasOwnProperty 限制循环只在对象自身,将被拷贝对象的每一个属性和值添加到创建的对象当中
  • 最后返回这个对象
    这与直接赋值var obj3 = obj1的区别如下:
name 和原数据是否指向同一对象 第一层数据为基本数据类型 原数据中包含子对象
赋值 改变会使原数据一同改变 改变会使原数据一同改变
浅拷贝 改变不会使原数据一同改变 改变会使原数据一同改变

(2)ES6的Object.assign

demo2.png

Object.assign:用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target),并返回合并后的target
用法: Object.assign(target, source1, source2); 所以 copyObj = Object.assign({}, obj); 这段代码将会把obj中的一级属性都拷贝到 {}中,然后将其返回赋给copyObj

(3)ES6扩展运算符

demo3.png

扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中

(4)Array.prototype.slice()
(5)Array.prototype.concat()
.....
实现浅拷贝的方法还有很多,只需要记住浅拷贝的定义浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变

深拷贝

(1)递归调用浅拷贝
demo4.png

对于深拷贝的对象,改变源对象不会对得到的对象有影响。只是在拷贝的过程中源对象的方法丢失了,这是因为在序列化 JavaScript 对象时,所有函数和原型成员会被有意忽略。

(2)JSON.stringify()和JSON.parse()

stringify 可以把一个 js 对象序列化为一个 JSON 字符串,parse 可以把 JSON 字符串反序列化为一个 js 对象

demo5.png

但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。
这种方法能正确处理的对象只有可以转成JSON格式的对象才可以这样用( Number, String, Boolean, Array,...)

(3)其他框架或者库都提供了深拷贝的方法,比如lodash,Jquery等等

总结

代码地址

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容