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 相关文章推荐
Confirmer JQuery确认对话框组件
Jun 09 Javascript
jQuery UI 应用不同Theme的办法
Sep 12 Javascript
js 三级关联菜单效果实例
Aug 13 Javascript
使用js判断当前时区TimeZone是否是夏令时
Feb 23 Javascript
Javascript中设置默认参数值示例
Sep 11 Javascript
Node.js实现的简易网页抓取功能示例
Dec 05 Javascript
原生js实现类似弹窗抖动效果
Apr 02 Javascript
一道优雅面试题分析js中fn()和return fn()的区别
Jul 05 Javascript
很实用的js选项卡切换效果
Aug 12 Javascript
jQuery tip提示插件(实例分享)
Apr 28 jQuery
JS html事件冒泡和事件捕获操作示例
May 01 Javascript
微信小程序点击按钮动态切换input的disabled禁用/启用状态功能
Mar 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
调频问题解答
2021/03/01 无线电
php+mysql分页代码详解
2008/03/27 PHP
php 远程图片保存到本地的函数类
2008/12/08 PHP
PHP对象相关知识总结
2017/04/09 PHP
PHP实现的XXTEA加密解密算法示例
2018/08/28 PHP
laravel5.1 ajax post 传值_token示例
2019/10/24 PHP
新手快速学习JavaScript免费教程资源汇总
2015/06/25 Javascript
JS延时提示框实现方法详解
2015/11/26 Javascript
angularjs创建弹出框实现拖动效果
2020/08/25 Javascript
jQuery控制文本框只能输入数字和字母及使用方法
2016/05/26 Javascript
jquery,js简单实现类似Angular.js双向绑定
2017/01/13 Javascript
详解Vue中状态管理Vuex
2017/05/11 Javascript
vue地区选择组件教程详解
2018/05/04 Javascript
vue将毫秒数转化为正常日期格式的实例
2018/09/16 Javascript
vue项目打包之开发环境和部署环境的实现
2020/04/23 Javascript
go语言计算两个时间的时间差方法
2015/03/13 Python
python创建关联数组(字典)的方法
2015/05/04 Python
Python操作SQLite数据库的方法详解【导入,创建,游标,增删改查等】
2017/07/11 Python
Python3.4学习笔记之 idle 清屏扩展插件用法分析
2019/03/01 Python
PyCharm+Qt Designer+PyUIC安装配置教程详解
2019/06/13 Python
python使用 zip 同时迭代多个序列示例
2019/07/06 Python
python如何爬取网站数据并进行数据可视化
2019/07/08 Python
Python获取统计自己的qq群成员信息的方法
2019/11/15 Python
Python semaphore evevt生产者消费者模型原理解析
2020/03/18 Python
python用opencv完成图像分割并进行目标物的提取
2020/05/25 Python
python基于socket模拟实现ssh远程执行命令
2020/12/05 Python
全球独特生活方式产品和礼品购物网站:AHAlife
2018/09/18 全球购物
main 函数执行以前,还会执行什么代码
2013/04/17 面试题
建龙钢铁面试总结
2014/04/15 面试题
一帮一活动总结
2014/05/08 职场文书
商铺门前三包责任书
2014/07/25 职场文书
自我管理的活动方案
2014/08/25 职场文书
党支部创先争优承诺书
2014/08/30 职场文书
2014年惩防体系建设工作总结
2014/12/01 职场文书
JS新手入门数组处理的实用方法汇总
2021/04/07 Javascript
CSS 实现多彩、智能的阴影效果
2021/05/12 HTML / CSS