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客户端将指定区域导出到Word、Excel的代码
Oct 22 Javascript
ff下JQuery无法监听input的keyup事件的解决方法
Dec 12 Javascript
javascript数组输出的两种方式
Jan 13 Javascript
JS常见问题之为什么点击弹出的i总是最后一个
Jan 05 Javascript
JS实现动态生成表格并提交表格数据向后端
Nov 25 Javascript
详解Vue.js 2.0 如何使用axios
Apr 21 Javascript
vue项目tween方法实现返回顶部的示例代码
Mar 02 Javascript
详解Webstorm 下的Angular2.0开发之路(图文)
Dec 06 Javascript
layer.js之回调销毁对话框的例子
Sep 11 Javascript
基于js判断浏览器是否支持webGL
Apr 18 Javascript
如何在Vue.JS中使用图标组件
Aug 04 Javascript
JS前端使用canvas实现扩展物体类和事件派发
Aug 05 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 图像尺寸调整代码
2010/05/26 PHP
php利用新浪接口查询ip获取地理位置示例
2014/01/20 PHP
Zend Framework分发器用法示例
2016/12/11 PHP
PHP实现微信图片上传到服务器的方法示例
2017/06/29 PHP
标题过长使用javascript按字节截取字符串
2014/04/24 Javascript
js清空表单数据的两种方式(遍历+reset)
2014/07/18 Javascript
JavaScript中具名函数的多种调用方式总结
2014/11/08 Javascript
JavaScript中的Array 对象(数组对象)
2016/06/02 Javascript
jquery实现ajax加载超时提示的方法
2016/07/23 Javascript
jquery.uploadifive插件怎么解决上传限制图片或文件大小问题
2017/05/08 jQuery
简单谈谈require模块化jquery和angular的问题
2017/06/23 jQuery
React Native之ListView实现九宫格效果的示例
2017/08/02 Javascript
jQuery实现的事件绑定功能基本示例
2017/10/11 jQuery
Bootstrap实现翻页效果
2017/11/27 Javascript
js实现HTML中Select二级联动的实例
2018/01/05 Javascript
详解node字体压缩插件font-spider的用法
2018/09/28 Javascript
Vue实现腾讯云点播视频上传功能的实现代码
2020/08/17 Javascript
uin-app+mockjs实现本地数据模拟
2020/08/26 Javascript
JavaScript中clientWidth,offsetWidth,scrollWidth的区别
2021/01/25 Javascript
python调用java的Webservice示例
2014/03/10 Python
python中sets模块的用法实例
2014/09/30 Python
约瑟夫问题的Python和C++求解方法
2015/08/20 Python
python之PyMongo使用总结
2017/05/26 Python
用Python下载一个网页保存为本地的HTML文件实例
2018/05/21 Python
读取json格式为DataFrame(可转为.csv)的实例讲解
2018/06/05 Python
Linux下多个Python版本安装教程
2018/08/15 Python
Python 实现遥感影像波段组合的示例代码
2019/08/04 Python
决策树剪枝算法的python实现方法详解
2019/09/18 Python
python3 assert 断言的使用详解 (区别于python2)
2019/11/27 Python
pytorch 改变tensor尺寸的实现
2020/01/03 Python
keras 权重保存和权重载入方式
2020/05/21 Python
快速创建python 虚拟环境
2020/11/28 Python
党员承诺书怎么写
2014/05/20 职场文书
美术社团活动总结
2014/06/27 职场文书
MySQL 十大常用字符串函数详解
2021/06/30 MySQL
python常见的占位符总结及用法
2021/07/02 Python