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 相关文章推荐
Ajax提交与传统表单提交的区别说明
Feb 07 Javascript
javascript中setTimeout的问题解决方法
May 08 Javascript
ajax+jQuery实现级联显示地址的方法
May 06 Javascript
JavaScript使ifram跨域相互访问及与PHP通信的实例
Mar 03 Javascript
JS数组操作(数组增加、删除、翻转、转字符串、取索引、截取(切片)slice、剪接splice、数组合并)
May 20 Javascript
全面解析Bootstrap中nav、collapse的使用方法
May 22 Javascript
vue proxyTable 接口跨域请求调试的示例
Sep 12 Javascript
jQuery实现滚动到底部时自动加载更多的方法示例
Feb 18 jQuery
element上传组件循环引用及简单时间倒计时的实现
Oct 01 Javascript
javascript对HTML字符转义与反转义
Dec 13 Javascript
vue.js实现二级菜单效果
Oct 19 Javascript
TypeScript魔法堂之枚举的超实用手册
Oct 29 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 zlib扩展实现页面GZIP压缩输出
2010/06/17 PHP
php对微信支付回调处理的方法
2018/08/23 PHP
总结PHP中初始化空数组的最佳方法
2019/02/13 PHP
js获取checkbox值的方法
2015/01/28 Javascript
JavaScript对数组进行随机重排的方法
2015/07/22 Javascript
JS实现输入框提示文字点击时消失效果
2016/07/19 Javascript
BootStrap table表格插件自适应固定表头(超好用)
2016/08/24 Javascript
javascript的函数劫持浅析
2016/09/26 Javascript
微信小程序 Page()函数详解
2016/10/17 Javascript
AngularJS入门教程之过滤器用法示例
2016/11/02 Javascript
VueJs路由跳转——vue-router的使用详解
2017/01/10 Javascript
JavaScript 栈的详解及实例代码
2017/01/22 Javascript
JavaScript实现图片切换效果
2017/08/12 Javascript
详解如何更好的使用module vuex
2019/03/27 Javascript
Vue动态修改网页标题的方法及遇到问题
2019/06/09 Javascript
JS实现移动端可折叠导航菜单(现代都市风)
2020/07/07 Javascript
python实现端口转发器的方法
2015/03/13 Python
Python 爬虫的工具列表大全
2016/01/31 Python
Python操作MySQL数据库的三种方法总结
2018/01/30 Python
Python实现连接MySql数据库及增删改查操作详解
2019/04/16 Python
利用pyinstaller打包exe文件的基本教程
2019/05/02 Python
python+selenium实现简历自动刷新的示例代码
2019/05/20 Python
Python3+Appium实现多台移动设备操作的方法
2019/07/05 Python
django 使用全局搜索功能的实例详解
2019/07/18 Python
使用浏览器访问python写的服务器程序
2019/10/10 Python
利用CSS3实现开门效果实例源码
2016/08/22 HTML / CSS
如何使用html5与css3完成google涂鸦动画
2012/12/16 HTML / CSS
床上用品全球在线购物:BeddingInn
2016/12/18 全球购物
韩国11街:11STREET
2018/03/27 全球购物
DERMAdoctor官网:美国著名皮肤护理品牌
2019/07/06 全球购物
戴尔英国翻新电脑和电子产品:Dell UK Refurbished Computers
2019/07/30 全球购物
党校学习心得体会范文
2014/09/09 职场文书
大学生赌博检讨书
2014/09/22 职场文书
六年级语文下册教学计划
2015/01/22 职场文书
2015年会计个人工作总结
2015/04/02 职场文书
电工实训心得体会
2016/01/14 职场文书