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 用Node.js写Shell脚本[译]
Sep 20 Javascript
Jquery中扩展方法extend使用技巧
Aug 24 Javascript
浅谈JavaScript中的Math.atan()方法的使用
Jun 14 Javascript
javascript实现框架高度随内容改变的方法
Jul 23 Javascript
JavaScript闭包实例详解
Jun 03 Javascript
js canvas实现QQ拨打电话特效
May 10 Javascript
解决webpack打包速度慢的解决办法汇总
Jul 06 Javascript
vue中阻止click事件冒泡,防止触发另一个事件的方法
Feb 08 Javascript
jQuery+koa2实现简单的Ajax请求的示例
Mar 06 jQuery
vue实现todolist基本功能以及数据存储功能实例详解
Apr 11 Javascript
微信小程序时间戳转日期的详解
Apr 30 Javascript
小程序实现搜索界面 小程序实现推荐搜索列表效果
May 18 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
php 文件上传实例代码
2012/04/19 PHP
解析php利用正则表达式解决采集内容排版的问题
2013/06/20 PHP
MongoDB在PHP中的常用操作小结
2014/02/20 PHP
smarty模板引擎中内建函数if、elseif和else的使用方法
2015/01/22 PHP
php实现通用的信用卡验证类
2015/03/24 PHP
详解php的socket通信
2015/08/11 PHP
JS中的public和private对象,即static修饰符
2012/01/18 Javascript
onkeypress字符按键兼容所有浏览器使用介绍
2013/04/24 Javascript
Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
2013/11/14 Javascript
JS+CSS实现可拖动的弹出提示框
2015/02/16 Javascript
JavaScript中的this关键字使用方法总结
2015/03/13 Javascript
js实现精美的银灰色竖排折叠菜单
2015/05/16 Javascript
js的flv视频播放器插件使用方法
2015/06/23 Javascript
微信小程序的分类页面制作
2017/06/27 Javascript
微信小程序 转发功能的实现
2017/08/04 Javascript
jQuery获取复选框选中的当前行的某个字段的值
2017/09/15 jQuery
React实现全局组件的Toast轻提示效果
2018/09/21 Javascript
js实现web调用摄像头 js截取视频画面
2019/04/21 Javascript
微信小程序框架的页面布局代码
2019/08/17 Javascript
vue框架制作购物车小球动画效果实例代码
2019/09/26 Javascript
Python迭代用法实例教程
2014/09/08 Python
Python工程师面试题 与Python基础语法相关
2016/01/14 Python
Python Sqlite3以字典形式返回查询结果的实现方法
2016/10/03 Python
windows系统下Python环境搭建教程
2017/03/28 Python
python如何实现int函数的方法示例
2018/02/19 Python
Python中logging实例讲解
2019/01/17 Python
税务干部鉴定材料
2014/02/11 职场文书
经济管理自荐书
2014/06/09 职场文书
房地产营销活动策划方案
2014/09/15 职场文书
刑事代理授权委托书
2014/09/17 职场文书
儿园租房协议书范本
2014/12/02 职场文书
骨干教师个人总结
2015/02/11 职场文书
幼儿园中秋节活动总结
2015/03/23 职场文书
2019财务毕业实习报告
2019/06/27 职场文书
Win11 Build 22000.51版本文件资源管理器“命令栏”和上下文菜单有什么新变化?
2021/11/21 数码科技
CentOS7和8下安装Maven3.8.4
2022/04/07 Servers