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 相关文章推荐
jQuery 技巧大全(新手入门篇)
May 12 Javascript
JavaScript访问样式表代码
Oct 15 Javascript
wap图片滚动特效无css3元素纯js脚本编写
Aug 22 Javascript
JavaScript获得表单target属性的方法
Apr 02 Javascript
深入浅析同源策略和跨域访问
Nov 26 Javascript
javascript+HTML5 Canvas绘制转盘抽奖
May 16 Javascript
jquery实现网页定位导航
Aug 23 Javascript
微信开发 JS-SDK 6.0.2 经常遇到问题总结
Dec 08 Javascript
JS实现预加载视频音频/视频获取截图(返回canvas截图)
Oct 09 Javascript
微信小程序6位或多位验证码密码输入框功能的实现代码
May 29 Javascript
微信小程序学习总结(三)条件、模板、文件引用实例分析
Jun 04 Javascript
关于ES6尾调用优化的使用
Sep 11 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实现的返回数据格式化类实例
2014/09/22 PHP
PHP读取配置文件类实例(可读取ini,yaml,xml等)
2015/07/28 PHP
Laravel最佳分割路由文件(routes.php)的方式
2016/08/04 PHP
一个加密JavaScript的开源工具PACKER2.0.2
2006/11/04 Javascript
JavaScript获得url查询参数的方法
2015/07/02 Javascript
SWFObject基本用法实例分析
2015/07/20 Javascript
全面解析Bootstrap表单使用方法(表单控件状态)
2015/11/24 Javascript
AngularJS控制器详解及示例代码
2016/08/16 Javascript
js 判断各种数据类型的简单方法(推荐)
2016/08/29 Javascript
jQuery extend()详解及简单实例
2017/05/06 jQuery
vue vuex vue-rouert后台项目——权限路由(适合初学)
2017/12/29 Javascript
JS实现点击按钮可实现编辑功能
2018/07/03 Javascript
vue项目打包之后背景样式丢失的解决方案
2019/01/17 Javascript
php结合js实现多条件组合查询
2019/05/28 Javascript
用vue 实现手机触屏滑动功能
2020/05/28 Javascript
[43:18]NB vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.22
2019/09/05 DOTA
使用Python生成随机密码的示例分享
2016/02/18 Python
Python3使用requests登录人人影视网站的方法
2016/05/11 Python
举例讲解Python中字典的合并值相加与异或对比
2016/06/04 Python
Python urls.py的三种配置写法实例详解
2017/04/28 Python
Ubuntu16.04/树莓派Python3+opencv配置教程(分享)
2018/04/02 Python
python 字典修改键(key)的几种方法
2018/08/10 Python
selenium+python 对输入框的输入处理方法
2018/10/11 Python
详解Django+uwsgi+Nginx上线最佳实战
2019/03/14 Python
解决python3插入mysql时内容带有引号的问题
2020/03/02 Python
Prometheus开发中间件Exporter过程详解
2020/11/30 Python
CSS3 实现的火焰动画
2020/12/07 HTML / CSS
Bravofly德国:预订廉价航班和酒店
2019/09/22 全球购物
全球性的众包图形设计市场:DesignCrowd
2021/02/02 全球购物
当我正在为表建立索引的时候,SQL Server 会禁止对表的访问吗
2014/04/28 面试题
专升本自我鉴定
2013/10/10 职场文书
航海技术专业毕业生推荐信
2014/07/09 职场文书
小学感恩节活动策划方案
2014/10/06 职场文书
湖南省党的群众路线教育实践活动总结会议新闻稿
2014/10/21 职场文书
默认网关不可用修复后过一会又不好使了解决方法
2022/04/08 数码科技
APP界面设计技巧和注意事项
2022/04/29 杂记