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 相关文章推荐
阻止JavaScript事件冒泡传递(cancelBubble 、stopPropagation)
May 08 Javascript
jquery下操作HTML控件的实现代码
Jan 12 Javascript
javascript 面向对象的JavaScript类
May 04 Javascript
js时间日期和毫秒的相互转换
Feb 22 Javascript
wap手机图片滑动切换特效无css3元素js脚本编写
Jul 28 Javascript
avalon js实现仿微博拖动图片排序
Aug 14 Javascript
浅谈jQuery this和$(this)的区别及获取$(this)子元素对象的方法
Nov 29 Javascript
JS定时检测任务任务完成后执行下一步的解决办法
Dec 22 Javascript
vue2.x 父组件监听子组件事件并传回信息的方法
Jul 17 Javascript
javascript中一些奇葩的日期换算方法总结
Nov 14 Javascript
javascript中数组的常用算法深入分析
Mar 12 Javascript
JS如何实现封装列表右滑动删除收藏按钮
Jul 23 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
WordPress判断用户是否登录的代码
2011/03/17 PHP
php小型企业库存管理系统的设计与实现代码
2011/05/16 PHP
PHP去掉从word直接粘贴过来的没有用格式的函数
2012/10/29 PHP
PHP生成压缩文件实例
2015/02/07 PHP
PHPTree――php快速生成无限级分类
2018/03/30 PHP
php让json_encode不自动转义斜杠“/”的方法
2020/04/27 PHP
Javascript 页面模板化很多人没有使用过的方法
2012/06/05 Javascript
jQuery实现图片左右滚动特效
2020/04/20 Javascript
DOM操作和jQuery实现选项移动操作的简单实例
2016/06/07 Javascript
js基于cookie记录来宾姓名的方法
2016/07/19 Javascript
Vue中添加过渡效果的方法
2017/03/16 Javascript
详解AngularJS用Interceptors来统一处理HTTP请求和响应
2017/06/08 Javascript
vue2+el-menu实现路由跳转及当前项的设置方法实例
2017/11/07 Javascript
vue 使用eventBus实现同级组件的通讯
2018/03/02 Javascript
jQuery实现的自定义轮播图功能详解
2018/12/28 jQuery
Vue 实现前进刷新后退不刷新的效果
2019/06/14 Javascript
JavaScript中Dom操作实例详解
2019/07/08 Javascript
Javascript作用域和作用域链原理解析
2020/03/03 Javascript
[01:19]DOTA2城市挑战赛报名开始 开启你的城市传奇
2018/03/23 DOTA
python+selenium识别验证码并登录的示例代码
2017/12/21 Python
解决Python获取字典dict中不存在的值时出错问题
2018/10/17 Python
opencv3/C++实现视频背景去除建模(BSM)
2019/12/11 Python
Python2.7:使用Pyhook模块监听鼠标键盘事件-获取坐标实例
2020/03/14 Python
python实现读取类别频数数据画水平条形图案例
2020/04/24 Python
Python中三维坐标空间绘制的实现
2020/09/22 Python
DJI大疆无人机官方商城:全球领先的无人飞行器研发和生产商
2016/12/21 全球购物
美国智能家居专家:tink
2019/06/04 全球购物
莫斯科的韩国化妆品店:Sifo
2019/12/04 全球购物
大学毕业后的十年规划
2014/01/07 职场文书
表决心的诗句大全
2014/03/11 职场文书
小学生家长寄语
2014/04/02 职场文书
讲座通知范文
2015/04/23 职场文书
2015年幼儿园国庆节活动总结
2015/07/30 职场文书
2015年庆祝国庆节66周年演讲稿
2015/07/30 职场文书
暑假开始了,你的暑假学习计划写好了吗?
2019/07/04 职场文书
html中两种获取标签内的值的方法
2022/06/10 HTML / CSS