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 相关文章推荐
Jquery实现的tab效果可以指定默认显示第几页
Oct 16 Javascript
js判断游览器类型及版本号的代码
May 11 Javascript
jQuery实现动画效果circle实例
Aug 06 Javascript
Node.js的环境安装配置(使用nvm方式)
Oct 11 Javascript
JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法
Apr 28 Javascript
JQuery判断正整数整理小结
Aug 21 jQuery
vue如何判断dom的class
Apr 26 Javascript
vue踩坑记录之数组定义和赋值问题
Mar 20 Javascript
jsonp格式前端发送和后台接受写法的代码详解
Nov 07 Javascript
JS 遍历 json 和 JQuery 遍历json操作完整示例
Nov 11 jQuery
详解vue中在父组件点击按钮触发子组件的事件
Nov 13 Javascript
微信小程序 根据不同用户切换不同TabBar
Apr 21 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
phpinfo 系统查看参数函数代码
2009/06/05 PHP
基于pear auth实现登录验证
2010/02/26 PHP
php中用socket模拟http中post或者get提交数据的示例代码
2013/08/08 PHP
利用PHP判断文件是否为图片的方法总结
2017/01/06 PHP
thinkphp 字母函数详解T/I/N/D/M/A/R/U
2017/04/03 PHP
Laravel实现定时任务的示例代码
2017/08/10 PHP
关于laravel 数据库迁移中integer类型是无法指定长度的问题
2019/10/09 PHP
js二维数组排序的简单示例代码
2014/01/24 Javascript
JavaScript事件委托实例分析
2015/05/26 Javascript
JS实现鼠标滑过链接改变网页背景颜色的方法
2015/10/20 Javascript
jquery特效 点击展示与隐藏全文
2015/12/09 Javascript
jquery实现点击弹出可放大居中及关闭的对话框(附demo源码下载)
2016/05/10 Javascript
微信小程序实现slideUp、slideDown滑动效果及点击空白隐藏功能示例
2018/12/11 Javascript
微信小程序日历组件使用方法详解
2018/12/29 Javascript
JavaScript鼠标悬停事件用法解析
2020/05/15 Javascript
一行JavaScript代码如何实现瀑布流布局
2020/12/11 Javascript
[01:07:15]DOTA2-DPC中国联赛 正赛 DLG vs XG BO3 第二场 1月25日
2021/03/11 DOTA
Python网页解析利器BeautifulSoup安装使用介绍
2015/03/17 Python
python简单实现旋转图片的方法
2015/05/30 Python
tensorflow更改变量的值实例
2018/07/30 Python
python代理工具mitmproxy使用指南
2019/07/04 Python
Python在OpenCV里实现极坐标变换功能
2019/09/02 Python
分享一个pycharm专业版安装的永久使用方法
2019/09/24 Python
Python的赋值、深拷贝与浅拷贝的区别详解
2020/02/12 Python
Django添加bootstrap框架时无法加载静态文件的解决方式
2020/03/27 Python
有关pycharm登录github时有的时候会报错connection reset的问题
2020/09/15 Python
Python更改pip镜像源的方法示例
2020/12/01 Python
Opencv 图片的OCR识别的实战示例
2021/03/02 Python
阿根廷首家户外用品制造商和经销商:Montagne
2018/02/12 全球购物
Ibatis如何调用存储过程
2015/05/15 面试题
团代会主持词
2014/04/02 职场文书
公司户外活动总结
2014/07/04 职场文书
基层党员四风问题自我剖析材料
2014/09/29 职场文书
欢迎新生标语
2014/10/06 职场文书
酒会开场白大全
2015/06/01 职场文书
导游词之山东八仙过海景区
2019/11/11 职场文书