如何在JS里进行深拷贝

什么是深拷贝?

深拷贝是指创建新对象的时候,对象拥有原始对象的所有属性的副本。

浅拷贝是指创建的新对象包含有原始对象的引用。也就是说浅拷贝仅复制对象的第一层结构,而不会递归地复制嵌套的对象数据。

如果仅使用浅拷贝创建对象的话,对新对象的更改,如果更改的是引用数据类型的属性时候,会改动原始对象。在实际应用中,我们期望对对象所做的修改不会影响到原对象,因此就需要使用深拷贝来复制对象。

深拷贝的方法

1. 使用 JSON.parse() 与 JSON.stringify()

这是一种简单的实现方式,先把对象使用stringify序列化,然后再用 parse 把它重新解析为对象,从而得到一个全新的对象。

javascript 复制代码
const original = { a: 1, b: 2, c: { d: 3 } };
const copied = JSON.parse(JSON.stringify(original));

一般不推荐使用这种方式进行深拷贝,原因有:

  • 无法复制函数,undefined,Symbol等
  • 性能比较低

2. 使用结构化克隆 structuredClone()

这是一个javascript原生支持的深拷贝方法,可以很方便地进行深拷贝。

看看它在各个浏览器以及node的支持情况:

javascript 复制代码
const original = { a: 1, b: 2, c: { d: 3 }};
const copied = structuredClone(original);
复制代码

如果浏览器或者node环境支持这个方法的话,推荐使用结构化克隆方案。

3. 使用递归

通过递归遍历对象各个属性进行拷贝。

javascript 复制代码
function deepClone(obj) {
    if (obj === null) return null;
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj);
    if (typeof obj !== 'object') return obj;

    const cloneObj = new obj.constructor();

    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            cloneObj[key] = deepClone(obj[key]);
        }
    }
    return cloneObj;
}

const original = { a: 1, b: 2, c: { d: 3, e: new Date() }, x: [1,2,3]};
const copied = deepClone(original);

4. 使用三方库 lodash.cloneDeep()

lodash 库提供了很多很有用的工具类,如果项目里面已经有使用lodash的话,直接使用它的深拷贝也是可以的。

如果单纯为了深拷贝而引入三方库的话,那就要斟酌斟酌了,毕竟引入一个三方库还是会导致安装包增大不少的。

javascript 复制代码
// 需要引入 Lodash 库
const _ = require('lodash');
const original = { a: 1, b: { c: 2 } };
const copied = _.cloneDeep(original);

总结

尽量使用结构化克隆 structuredClone,避免使用JSON方式。

相关推荐
another heaven3 小时前
【C/C++ Ranges 是零开销抽象吗?拆开管道、惰性求值和编译期膨胀】
c语言·开发语言·c++
SomeOtherTime4 小时前
Rust 闭包语法和原理(AI回答)
开发语言·后端·rust
apcipot_rain4 小时前
C++转Java日记(10)
java·开发语言
总要学点什么5 小时前
第105篇:三维特效-流动图片墙体效果——让箭头沿墙长滚,它俩竟是同一份代码
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
xiaoye-duck5 小时前
《C++ 项目:手写大模型接入 SDK》会话模块整合:内存 SessionManager 与 DataManager 持久化联动
开发语言·数据库·c++·语言模型
Agent世界6 小时前
用 CDP 做发布自动化:四道机器闸门与产物验收
前端·javascript
Funlang6 小时前
龙芯上的 Fun:从跑起来到机器码
开发语言·龙芯
总要学点什么7 小时前
第104篇:三维特效-流动墙体效果——让贴图沿墙流动,它却只肯走一条对角线
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
程序员大阳7 小时前
副队长ES6+教程(3)--解构赋值
前端·javascript·es6·赋值·解构
旖旎夜光7 小时前
【C++ 基础入门】C++11 新特性(中):右值引用、移动语义与完美转发
开发语言·c++·笔记·学习