JS的深浅复制详细


Posted in Javascript onOctober 16, 2021

1、浅复制的意思

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

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'

2、深复制的意思

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

3、使用深复制的原由

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

4、可实现深复制的几种方法

实现方式一: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);  // 1
console.log(objA.a);  // 'a'

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

  • date日期对象被转成日期日期字符串
  • 没法访问到原型
  • 复制不了undefined的属性
  • 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);  // 1
console.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);  // 1
console.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);  // 10
console.log(objA.c.c1);  // 'c1'

5、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);  // 10
console.log(objA.c.c1);  // 'c1'

到此这篇关于JS的深浅复制详细的文章就介绍到这了,更多相关JS的深浅复制内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
js 单引号 传递方法
Jun 22 Javascript
JavaScript中的类继承
Nov 25 Javascript
javascript测试题练习代码
Oct 10 Javascript
JavaScript实现数组随机排序的方法
Jun 26 Javascript
jquery实现简单的banner轮播效果【实例】
Mar 30 Javascript
JS实现的相册图片左右滚动完整实例
Nov 23 Javascript
jQuery弹出层插件popShow(改进版)用法示例
Jan 23 Javascript
AngularJS监听ng-repeat渲染完成的方法
Mar 20 Javascript
vue-content-loader内容加载器的使用方法
Aug 05 Javascript
jquery图片预览插件实现方法详解
Jul 18 jQuery
使用layer.msg 时间设置不起作用的解决方法
Sep 12 Javascript
原生JS与CSS实现软件卸载对话框功能
Dec 05 Javascript
JS 基本概念详细介绍
Oct 16 #Javascript
AJAX实现指定部分页面刷新效果
AJAX实现省市县三级联动效果
Oct 16 #Javascript
简单聊聊Vue中的计算属性和属性侦听
Oct 05 #Vue.js
JS中如何优雅的使用async await详解
Oct 05 #Javascript
js中Object.create实例用法详解
Oct 05 #Javascript
TypeScript中条件类型精读与实践记录
Oct 05 #Javascript
You might like
利用discuz实现PHP大文件上传应用实例代码
2008/11/14 PHP
PHP中ob_start函数的使用说明
2013/11/11 PHP
WordPress中设置Post Type自定义文章类型的实例教程
2016/05/10 PHP
Smarty环境配置与使用入门教程
2016/05/11 PHP
PHP中实现中文字串截取无乱码的解决方法
2018/05/29 PHP
Nigma vs Liquid BO3 第一场2.14
2021/03/10 DOTA
nodejs分页类代码分享
2014/06/17 NodeJs
javascript 常用验证函数总结
2016/06/28 Javascript
angular ngClick阻止冒泡使用默认行为的方法
2016/11/03 Javascript
微信小程序 ES6Promise.all批量上传文件实现代码
2017/04/14 Javascript
python实现红包裂变算法
2016/02/16 Python
python实现简易云音乐播放器
2018/01/04 Python
python3调用R的示例代码
2018/02/23 Python
pandas DataFrame 根据多列的值做判断,生成新的列值实例
2018/05/18 Python
python爬虫框架scrapy实现模拟登录操作示例
2018/08/02 Python
用python标准库difflib比较两份文件的异同详解
2018/11/16 Python
Linux CentOS Python开发环境搭建教程
2018/11/28 Python
Python如何使用BeautifulSoup爬取网页信息
2019/11/26 Python
Python JSON常用编解码方法代码实例
2020/09/05 Python
python爬虫爬取图片的简单代码
2021/01/18 Python
StubHub西班牙:购买和出售全球活动门票
2017/06/05 全球购物
ALDO英国官网:加拿大女鞋品牌
2018/02/19 全球购物
英国领先的独立时装店:Van Mildert
2019/10/28 全球购物
美国电子产品购物网站:BuyDig.com
2020/06/17 全球购物
北京麒麟网信息技术有限公司网络游戏测试面试题
2013/09/28 面试题
企事业单位求职者的自我评价
2013/12/28 职场文书
学习全国两会精神心得体会范文
2014/03/17 职场文书
交通文明倡议书
2014/05/16 职场文书
王力宏牛津大学演讲稿
2014/05/22 职场文书
乡镇精神文明建设汇报材料
2014/08/15 职场文书
2016大学生社会实践心得体会范文
2016/01/14 职场文书
2016年法制宣传月活动总结
2016/04/01 职场文书
教你如何使用Python下载B站视频的详细教程
2021/04/29 Python
Golang中异常处理机制详解
2021/06/08 Golang
详解python网络进程
2021/06/15 Python
MySQL 那些常见的错误设计规范,你都知道吗
2021/07/16 MySQL