当前位置: 首页 > news >正文

javascript 深拷贝和浅拷贝的区别及具体实现方案

一、核心区别

特性浅拷贝深拷贝
复制层级仅复制对象的第一层属性递归复制对象的所有层级属性(包括嵌套对象和数组)
引用关系嵌套对象/数组与原对象共享内存(引用拷贝)嵌套对象/数组与原对象完全独立(值拷贝)
修改影响修改拷贝后的嵌套属性会影响原对象修改拷贝后的任何属性都不会影响原对象
适用场景简单数据结构,无需嵌套独立性复杂数据结构,要求完全独立

二、浅拷贝实现方案

1. 对象浅拷贝
  • Object.assign()
    const obj = { a: 1, b: { c: 2 } };
    const shallowCopy = Object.assign({}, obj);
    
  • 展开运算符(...
    const obj = { a: 1, b: { c: 2 } };
    const shallowCopy = { ...obj };
    
2. 数组浅拷贝
  • Array.prototype.slice()
    const arr = [1, 2, [3, 4]];
    const shallowCopy = arr.slice();
    
  • 展开运算符(...
    const arr = [1, 2, [3, 4]];
    const shallowCopy = [...arr];
    

三、深拷贝实现方案

1. JSON 序列化法

原理:通过 JSON.stringify()JSON.parse() 序列化对象。
优点:简单快捷,适合纯数据对象。
缺点:无法处理函数、undefinedSymbolDateRegExp、循环引用等。

const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
2. 递归深拷贝(手动实现)

原理:递归遍历对象属性,处理所有数据类型。
优点:可自定义逻辑,支持复杂场景。
缺点:需处理边界条件(如循环引用)。

function deepClone(source, hash = new WeakMap()) {// 处理基本类型和 null/undefinedif (source === null || typeof source !== 'object') return source;// 处理循环引用if (hash.has(source)) return hash.get(source);// 处理 Date 和 RegExpif (source instanceof Date) return new Date(source);if (source instanceof RegExp) return new RegExp(source);// 初始化拷贝对象(保持原型链)const target = new source.constructor();hash.set(source, target);// 遍历所有属性(包括 Symbol)Reflect.ownKeys(source).forEach(key => {target[key] = deepClone(source[key], hash);});return target;
}
3. 第三方库实现
  • Lodash(推荐)

    import { cloneDeep } from 'lodash';
    const deepCopy = cloneDeep(obj);
    
  • jQuery

    const deepCopy = $.extend(true, {}, obj);
    

四、特殊场景处理

1. 循环引用

问题:对象属性间接引用自身,导致递归栈溢出。
解决方案:使用 WeakMap 缓存已拷贝对象。

const obj = { a: 1 };
obj.self = obj; // 循环引用
const copy = deepClone(obj); // 递归实现中通过 WeakMap 避免死循环
2. 处理特殊对象
  • Date 对象:通过 new Date(source.getTime()) 重建。
  • RegExp 对象:通过 new RegExp(source.source, source.flags) 重建。
  • Map/Set:遍历并递归拷贝每个元素。
3. 函数拷贝

问题:函数无法被完全拷贝(可能依赖闭包环境)。
解决方案:通过 evalnew Function 重建函数(需谨慎使用)。

五、性能对比与选型建议

方法性能功能完整性安全性
JSON 法低(丢失类型)安全
递归实现需处理边界
Lodash安全

选型建议

  • 纯数据对象且无特殊类型 → JSON 法
  • 复杂对象或需要保留类型 → Lodash 的 cloneDeep
  • 定制化需求 → 手动递归实现

六、验证示例

const origin = { a: 1, b: { c: 2 }, d: new Date(), e: /regex/, f: function() { console.log('test') },g: [1, 2, { h: 3 }]
};
origin.self = origin; // 循环引用const copy = deepClone(origin);// 验证
console.log(copy.b === origin.b); // false(深拷贝成功)
console.log(copy.d instanceof Date); // true(保留类型)
console.log(copy.self === copy); // true(循环引用处理成功)

http://www.xdnf.cn/news/233749.html

相关文章:

  • 【每日八股】复习 Redis Day4:线程模型
  • NLP 分词技术学习
  • 【Dify系列教程重置精品版】第四章:实现Dify的 hello world
  • ISO 26262认证步骤
  • 【Java面试笔记:进阶】30.Java程序运行在Docker等容器环境有哪些新问题?
  • 楼宇智能化三、五章【期末复习】
  • 芯知识|小体积语音芯片方案WTV/WT2003H声音播放ic应用解析
  • 楼宇智能化四章【期末复习】
  • (eNSP)Smart Link配置实验
  • MicroPython for esp32s3开发HX711称重模块指南
  • rk3568 A/B系统 OAT升级 实践
  • 全面了解CSS语法 ! ! !
  • 聊一聊接口自动化测试断言处理策略
  • 用户意图驱动:GEO优化策略之内容精准匹配
  • PID中低通滤波算法的详细讲解
  • 消防岗位技能竞赛流程方案策划
  • verilog_testbench技巧
  • 逻辑回归之参数选择:从理论到实践
  • [FPGA VIDEO IP] VCU
  • Allegro23.1新功能之新型via structure创建方法操作指导
  • 20250430在ubuntu14.04.6系统上完成编译NanoPi NEO开发板的FriendlyCore系统【严重不推荐,属于没苦硬吃】
  • 两向量平行公式、向量与平面平行公式、两平面平行公式;两向量垂直公式、向量与平面垂直公式、两平面垂直公式
  • 2025年数字创意设计与图像处理国际会议 (DCDIP 2025)
  • 一种导弹追踪算法的MATLAB仿真实现
  • HTML5 新增的主要标签整理
  • 10. 你需了解的原生测试框架Unittest断言的使用
  • 开源项目[Heygem]可商用的本地运行AI数字人!支持离线运行、本地API接口调用(喂饭级安装教程)
  • ‌连续流型液氮恒温器核心特点解析
  • 望获实时Linux系统荣获人形机器人技术突破奖
  • 【Token系列】14|Prompt不是文本,是token结构工程