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 相关文章推荐
js中if语句的几种优化代码写法
Mar 12 Javascript
js生成随机数之random函数随机示例
Dec 20 Javascript
jquery实现的一个文章自定义分段显示功能
May 23 Javascript
jQuery中animate用法实例分析
Mar 09 Javascript
五种js判断是否为整数类型方式
Dec 03 Javascript
jquery获取input type=text中的值的各种方式(总结)
Dec 02 Javascript
JS中with的替代方法与String中的正则方法详解
Dec 23 Javascript
JavaScript实现事件的中断传播和行为阻止方法示例
Jan 20 Javascript
基于Bootstrap的网页设计实例
Mar 01 Javascript
使用Node.js搭建静态资源服务详细教程
Aug 02 Javascript
JS自定义函数实现时间戳转换成date的方法示例
Aug 27 Javascript
Vuejs开发环境搭建及热更新【推荐】
Sep 07 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
2020最新CPU的性能排名
2020/04/02 数码科技
DC这些乐高系列动画电影你看过几部?
2020/04/09 欧美动漫
php安装php_rar扩展实现rar文件读取和解压的方法
2016/11/17 PHP
php获取今日开始时间和结束时间的方法
2017/02/27 PHP
php获取字符串前几位的实例(substr返回字符串的子串用法)
2017/03/08 PHP
PHP如何通过带尾指针的链表实现'队列'
2020/10/22 PHP
DEFER怎么用?
2006/07/01 Javascript
js 表格隔行颜色
2009/12/02 Javascript
jQuery选中select控件 无法设置selected的解决方法
2010/09/01 Javascript
JavaScript.The.Good.Parts阅读笔记(二)作用域&闭包&减缓全局空间污染
2010/11/16 Javascript
jQuery学习笔记之控制页面实现代码
2012/02/27 Javascript
jquery live()调用不存在的解决方法
2014/02/26 Javascript
PHP使用方法重载实现动态创建属性的get和set方法
2014/11/17 Javascript
JavaScript学习笔记之基础语法
2015/01/22 Javascript
JS实现列表页面隔行变色效果
2017/03/25 Javascript
vue通过watch对input做字数限定的方法
2017/07/13 Javascript
JavaScript实现开关等效果
2017/09/08 Javascript
对vue.js中this.$emit的深入理解
2018/02/23 Javascript
vue源码学习之Object.defineProperty对象属性监听
2018/05/30 Javascript
微信小程序实现商品属性联动选择
2019/02/15 Javascript
js实现旋转的星空效果
2019/11/01 Javascript
[48:31]完美世界DOTA2联赛PWL S3 DLG vs Phoenix 第二场 12.17
2020/12/19 DOTA
利用Python的Twisted框架实现webshell密码扫描器的教程
2015/04/16 Python
python中pygame针对游戏窗口的显示方法实例分析(附源码)
2015/11/11 Python
Python 判断是否为质数或素数的实例
2017/10/30 Python
python3.6.3+opencv3.3.0实现动态人脸捕获
2018/05/25 Python
用python做游戏的细节详解
2019/06/25 Python
flask 实现token机制的示例代码
2019/11/07 Python
Python importlib动态导入模块实现代码
2020/04/16 Python
Django静态文件加载失败解决方案
2020/08/26 Python
澳大利亚冲浪和时尚服装网上购物:SurfStitch
2017/07/29 全球购物
中专毕业生自荐信范文
2013/11/28 职场文书
医院实习介绍信
2014/01/12 职场文书
药店促销活动策划方案
2014/08/24 职场文书
男人帮观后感
2015/06/18 职场文书
初二数学教学反思
2016/02/17 职场文书