写点什么

JS 的深浅复制,原来如此!

发布于: 刚刚

摘要:之所以会出现深浅拷贝的问题,实质上是由于 JS 对基本类型和引用类型的处理不同。

 

本文分享自华为云社区《js的深浅复制,一看就明白》,作者: 鑫 2020。

浅复制的意思


浅复制是仅仅对数据存放在栈内的引用的复制,没有复制引用指向堆内的内容。多个数据的浅复制,这复制多个引用,这多个引用共同指向堆内的同一个内容。当一个浅复制数据做出修改,即堆内的引用指向的内容发生修改,这时,其他通过引用指向这里的数据也会随着改变。


let obj = {    a:1,    b:2,    c:{        c1:10,        c2:20    }}
let objA = obj;objA.a = 'a';
console.log(obj.a); // 'a'console.log(objA.a); // 'a'
复制代码

深复制的意思


深复制是指连同堆的内容一块复制,生成一个新的对象。多个深复制将是多个不同的对象,也就有不同的引用,也就指向不同的堆内容。

使用深复制的原由


在平常开发中,有时会有数据的传递与接收,当拿到传过来的数据后,难免需要对数据进行加工和改造,为了不破坏原有数据结构,这时就可以使用深复制拷贝数据,然后处理生成的新的数据。深复制也可以防止修改多个引用后引用混乱的问题,减少 BUG 的产生机会。

可实现深复制的几种方法


实现方式一:JSON 的序列化与反序列化


let obj = {    a:1,    b:2,    c:{        c1:10,        c2:20    }}
let objA = JSON.parse(JSON.stringify(obj));//JSON的序列化与反序列化objA.a = 'a';
console.log(obj.a); // 1console.log(objA.a); // 'a'
复制代码


虽然 JSON 的序列化与反序列化可以实现深复制,但有几个缺点需要注意:

1、date 日期对象被转成日期日期字符串

2、没法访问到原型

3、复制不了 undefined 的属性

4、NAN 和无穷被转为 NULL


let d1 = new Date();let obj = {    d1,    d2: undefined,    d3:NaN}let objD = JSON.parse(JSON.stringify(obj));console.log(obj) console.log(objD)
复制代码


实现方式二:Object.assign()


let obj = {    a:1,    b:2,    c:{        c1:10,        c2:20    }}
let objA = Object.assign(obj);objA.a = 'a';
console.log(obj.a); // 1console.log(objA.a); // 'a'
复制代码


虽然 Object.assign()可以实现深复制,但对于更深层次的对象引用也是仅仅浅复制。


let obj = {    a:1,    b:2,    c:{        c1:10,        c2:20    }}
let objA = Object.assign(obj);objA.c.c1 = 'c1'; //Object.assign()仅仅是一层深复制。
console.log(obj.c.c1); // 'c1'console.log(objA.c.c1); // 'c1'
复制代码


实现方式三:扩展运算符


let obj = {    a:1,    b:2,    c:{        c1:10,        c2:20    }}
let objA = {...obj};;objA.a = 'a';
console.log(obj.a); // 1console.log(objA.a); // 'a'
复制代码


虽然扩展运算符"…"可以实现深复制,但对于更深层次的对象引用也是仅仅浅复制。


let obj = {    a:1,    b:2,    c:{        c1:10,        c2:20    }}
let objA = {...obj};objA.c.c1 = 'c1'; //扩展运算符"..."同Object.assign()一样,仅仅是一层深复制,不能多层深复制。
console.log(obj.c.c1); // 'c1'console.log(objA.c.c1); // 'c1'
复制代码


实现方式四:使用递归


想要实现深复制,且实现多层深复制则可以使用递归循环复制。


let obj = {    a:1,    b:2,    c:{        c1:10,        c2:20    }}
const ReCopy = function (paramter) { let target = null; let isObject = paramter.constructor === Object; let isArray = paramter.constructor === Array; if (isObject || isArray) { target = Array.isArray(paramter) ? [] : {}; for (let i in paramter) { target[i] = ReCopy(paramter[i]); } } else { target = paramter; } return target; }
let objA = ReCopy(obj);objA.c.c1 = 'c1';
console.log(obj.c.c1); // 10console.log(objA.c.c1); // 'c1'
复制代码

ladash 深拷贝


lodash 深复制是更专业的深复制方式。


  • 安装 lodash

先初始化,生成 package.json 文件,然后使用一下命令安装。


npm i -S lodash
复制代码


  • 引入 lodash


var _ = require('lodash');
复制代码


  • 使用 lodash


let obj = {    a:1,    b:2,    c:{        c1:10,        c2:20    }}
let objA = _.cloneDeep(obj);objA.c.c1 = 'c1';
console.log(obj.c.c1); // 10console.log(objA.c.c1); // 'c1'
复制代码


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 2
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
JS的深浅复制,原来如此!