Javascript中的深拷贝详解

ops/2025/2/20 21:59:35/

在 Javascript 开发中,深拷贝(Deep Clone)是一个经常遇到的问题。本文将详细介绍深拷贝的概念、实现方法以及注意事项。

什么是深拷贝?

在 Javascript 中,数据类型分为基本类型(如 Number、String、Boolean 等)和引用类型(如 Object、Array 等)。当我们复制引用类型数据时,如果仅仅进行浅拷贝,那么新变量和原变量会指向同一个内存地址,导致其中一个变量的修改会影响另一个变量。而深拷贝则是创建一个完全独立的副本,两个变量互不影响。

浅拷贝与深拷贝的区别

让我们通过一个简单的例子来理解:

javascript">// 浅拷贝示例
const original = { a: 1, b: { c: 2 } };
const shallowCopy = { ...original };shallowCopy.b.c = 3;
console.log(original.b.c); // 输出: 3// 深拷贝示例
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.b.c = 4;
console.log(original.b.c); // 输出: 3

常见的深拷贝实现方法

1. JSON.parse() + JSON.stringify()

这是最简单的深拷贝方法:

javascript">const deepClone = obj => JSON.parse(JSON.stringify(obj));

优点:

  • 实现简单
  • 可以处理嵌套对象

缺点:

  • 无法处理函数、undefined、Symbol
  • 无法处理循环引用
  • 会丢失对象的原型链

2. 递归实现

一个基础的递归实现方案:

javascript">function deepClone(obj) {if (obj === null || typeof obj !== 'object') {return obj;}const clone = Array.isArray(obj) ? [] : {};for (let key in obj) {if (Object.prototype.hasOwnProperty.call(obj, key)) {clone[key] = deepClone(obj[key]);}}return clone;
}

3. 使用第三方库

在实际项目中,我们常常使用成熟的第三方库来实现深拷贝:

javascript">// 使用 Lodash
const _ = require('lodash');
const deepCopy = _.cloneDeep(original);// 使用 structuredClone (新特性)
const deepCopy = structuredClone(original);

处理特殊情况

1. 循环引用

javascript">function deepCloneWithMap(obj, hash = new WeakMap()) {if (obj === null || typeof obj !== 'object') {return obj;}if (hash.has(obj)) {return hash.get(obj);}const clone = Array.isArray(obj) ? [] : {};hash.set(obj, clone);for (let key in obj) {if (Object.prototype.hasOwnProperty.call(obj, key)) {clone[key] = deepCloneWithMap(obj[key], hash);}}return clone;
}

2. 特殊类型的处理

javascript">function complexDeepClone(obj, hash = new WeakMap()) {// 处理 null 和非对象if (obj === null || typeof obj !== 'object') {return obj;}// 处理日期对象if (obj instanceof Date) {return new Date(obj);}// 处理正则表达式if (obj instanceof RegExp) {return new RegExp(obj);}// 处理循环引用if (hash.has(obj)) {return hash.get(obj);}const clone = Array.isArray(obj) ? [] : {};hash.set(obj, clone);// 处理可枚举属性Reflect.ownKeys(obj).forEach(key => {clone[key] = complexDeepClone(obj[key], hash);});return clone;
}

性能考虑

在实际开发中,需要根据具体场景选择合适的深拷贝方法:

  1. 对于简单对象,使用 JSON.parse(JSON.stringify()) 足够
  2. 对于包含特殊类型的复杂对象,使用递归实现或第三方库
  3. 对于频繁的深拷贝操作,考虑使用结构共享或不可变数据结构

最佳实践建议

  1. 优先使用 structuredClone() (如果浏览器支持)
  2. 如果项目中已经使用了 Lodash,推荐使用 _.cloneDeep()
  3. 对于简单数据结构,可以使用 JSON.parse(JSON.stringify())
  4. 需要处理特殊类型时,使用自定义的递归实现

总结

深拷贝是 Javascript 开发中的一个重要概念,选择合适的深拷贝方法对于代码的性能和可维护性都很重要。在实际开发中,我们需要根据具体场景选择最适合的实现方案,同时要注意处理好循环引用、特殊类型等边界情况。


http://www.ppmy.cn/ops/159687.html

相关文章

VMware按照的MacOS升级后无法联网

背景 3年前公司使用Flutter开发了一款app,现在app有微小改动需要重新发布到AppStore 问题 问题是原来的Vmware搭建的开发环境发布App失败了 提示:App需要使用xcode15IOS 17 SDK重新构建,这样的话MacOS至少需要升级到13.5 Xcode - 支持 - Ap…

【JavaScript】正则表达式综合案例

目录 1、正则表达式 1.1 什么是正则表达式 1.2 语法 test() 方法 用来查看正则表达式与指定的字符串是否匹配 exec() 方法 在一个指定字符串中执行一个搜索匹配 1.3 元字符 1. 边界符 2. 量词 3. 字符类: 案例 用户名验证案例 1.4 修饰符 案例 过滤…

从零开始构建一个小型字符级语言模型的详细教程(基于Transformer架构)之一数据准备

最近特别火的DeepSeek,是一个大语言模型,那一个模型是如何构建起来的呢?DeepSeek基于Transformer架构,接下来我们也从零开始构建一个基于Transformer架构的小型语言模型,并说明构建的详细步骤及内部组件说明。我们以构建一个字符级语言模型(Char-Level LM)为例,目标是通…

利用 UniApp 实现带有渐变背景的盒子

要实现一个带有渐变背景的盒子&#xff0c;我们需要使用 UniApp 的模板和样式部分。在模板部分创建一个视图容器&#xff08;<view>&#xff09;&#xff0c;在样式部分使用 CSS 的 linear-gradient 函数来设置渐变背景。 <template><view class"gradient-…

导轨与滑块之间松紧程度的调节方式

导轨与滑块之间的松紧程度对于设备的精度和稳定性有着重要的影响。以下是一些常用的调节方法&#xff1a; 1、清洁导轨表面&#xff1a;在调整之前&#xff0c;确保导轨表面清洁无尘&#xff0c;以避免杂质影响调整精度。 2、检查导轨安装&#xff1a;确保导轨安装在正确的位置…

智能选择+NAT

一 拓扑 二 FW的相关配置 接口 dns配置 三 安全策略 nat策略 IP-Link策略 ip-link check enable ip-link check name pb r_1 destination 13.0.0.3 interface G 1/0/1 ip-link check name pb r_2 destination 12.0.0.3 interface G 1/0/2 策略路由

Word中接入大模型教程

前言 为什么要在word中接入大模型呢&#xff1f; 个人觉得最大的意义就是不用来回切换与复制粘贴了吧。 今天分享一下昨天实践的在word中接入大模型的教程。 在word中接入大模型最简单的方式就是使用vba。 vba代码要做的事&#xff0c;拆分一下就是&#xff1a; 获取用户…

【蓝桥杯集训·每日一题2025】 AcWing 6123. 哞叫时间 python

6123. 哞叫时间 Week 1 2月18日 农夫约翰正在试图向埃尔茜描述他最喜欢的 USACO 竞赛&#xff0c;但她很难理解为什么他这么喜欢它。 他说「竞赛中我最喜欢的部分是贝茜说 『现在是哞哞时间』并在整个竞赛中一直哞哞叫」。 埃尔茜仍然不理解&#xff0c;所以农夫约翰将竞赛以…