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 相关文章推荐
JSON扫盲帖 JSON.as类教程
Feb 16 Javascript
jquery实现邮箱自动补全功能示例分享
Feb 17 Javascript
jQuery淡入淡出元素让其效果更为生动
Sep 01 Javascript
JavaScript高仿支付宝倒计时页面及代码实现
Oct 21 Javascript
js获取元素下的第一级子元素的方法(推荐)
Mar 05 Javascript
JavaScript中splice与slice的区别
May 09 Javascript
详解JavaScript调用栈、尾递归和手动优化
Jun 03 Javascript
基于Vue2x实现响应式自适应轮播组件插件VueSliderShow功能
May 16 Javascript
解决Js先触发失去焦点事件再执行点击事件的问题
Aug 30 Javascript
vue如何使用外部特殊字体的操作
Jul 30 Javascript
使用node-media-server搭建一个简易的流媒体服务器
Jan 20 Javascript
在JavaScript中如何使用宏详解
May 06 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
全国FM电台频率大全 - 9 上海市
2020/03/11 无线电
如何给phpadmin一个保护
2006/10/09 PHP
文章推荐系统(三)
2006/10/09 PHP
PHP 批量删除数据的方法分析
2009/10/30 PHP
PHP实现通过get方式识别用户发送邮件的方法
2015/07/16 PHP
php ActiveMQ的安装与使用方法图文教程
2020/02/23 PHP
YII2框架中日志的配置与使用方法实例分析
2020/03/18 PHP
javascript之querySelector和querySelectorAll使用说明
2011/10/09 Javascript
Linux下使用jq友好的打印JSON技巧分享
2014/11/18 Javascript
Vue.js第三天学习笔记(计算属性computed)
2016/12/01 Javascript
jquery,js简单实现类似Angular.js双向绑定
2017/01/13 Javascript
js 发布订阅模式的实例讲解
2017/09/10 Javascript
Three.js开发实现3D地图的实践过程总结
2017/11/20 Javascript
Angular父组件调用子组件的方法
2018/04/02 Javascript
基于Vue 服务端Cookies删除的问题
2018/09/21 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
2019/08/29 Javascript
vue3弹出层V3Popup实例详解
2021/01/04 Vue.js
[52:26]完美世界DOTA2联赛决赛 FTD vs Phoenix 第一场 11.08
2020/11/11 DOTA
在Python中操作列表之List.append()方法的使用
2015/05/20 Python
在Python的struct模块中进行数据格式转换的方法
2015/06/17 Python
完美解决Python2操作中文名文件乱码的问题
2017/01/04 Python
python简单线程和协程学习心得(分享)
2017/06/14 Python
python matplotlib中文显示参数设置解析
2017/12/15 Python
答题辅助python代码实现
2018/01/16 Python
Django 连接sql server数据库的方法
2018/06/30 Python
python 顺时针打印矩阵的超简洁代码
2018/11/14 Python
简单了解Python读取大文件代码实例
2019/12/18 Python
Python虚拟环境venv用法详解
2020/05/25 Python
HTML5拖放效果的实现代码
2016/11/17 HTML / CSS
美国鞋类购物网站:Shiekh Shoes
2016/08/21 全球购物
元旦联欢会感言
2014/03/04 职场文书
党员干部承诺书
2014/03/25 职场文书
高等教育专业自荐信范文
2014/03/26 职场文书
求职自荐信的格式
2014/04/07 职场文书
挂职个人工作总结
2015/03/05 职场文书
Pygame如何使用精灵和碰撞检测
2021/11/17 Python