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

JavaScript 中深拷贝浅拷贝的区别?如何实现一个深拷贝?

一、区别:像“复印文件” vs “创建副本文件”

1. 浅拷贝(Shallow Copy)
  • 动作:只复制文件的第一页,其他页用“贴标签”指向原文件。
  • 结果
    修改第一层属性不影响原对象,但修改嵌套对象会同时改变原对象和拷贝对象。
  • 例子
    const original = { a: 1, b: { c: 2 } };
    const shallowCopy = { ...original }; // 展开运算符(浅拷贝)shallowCopy.a = 100;    // 原对象不变:original.a = 1
    shallowCopy.b.c = 200;  // 原对象也被修改:original.b.c = 200
    
2. 深拷贝(Deep Copy)
  • 动作:把文件每一页都完整复印一份,完全独立。
  • 结果
    修改拷贝对象的任何属性都不会影响原对象。
  • 例子
    const original = { a: 1, b: { c: 2 } };
    const deepCopy = JSON.parse(JSON.stringify(original)); // 深拷贝deepCopy.a = 100;       // 原对象不变:original.a = 1
    deepCopy.b.c = 200;     // 原对象不变:original.b.c = 2
    

二、如何实现深拷贝?

方法1:JSON 序列化(简单但局限)
  • 代码
    function simpleDeepCopy(obj) {return JSON.parse(JSON.stringify(obj));
    }
    
  • 缺点
    • 无法拷贝函数、undefinedSymbol
    • 会丢失 Date 对象(转成字符串)、正则表达式(转成空对象)。
    • 无法处理循环引用(如 obj.self = obj)。

方法2:递归克隆(手动实现完整版)

代码步骤分解

function deepClone(obj, cache = new WeakMap()) {// 1. 处理基本类型和 null/undefinedif (obj === null || typeof obj !== 'object') return obj;// 2. 处理循环引用(避免无限递归)if (cache.has(obj)) return cache.get(obj);// 3. 处理特殊对象类型let clone;if (obj instanceof Date) {clone = new Date(obj); // 克隆日期} else if (obj instanceof RegExp) {clone = new RegExp(obj); // 克隆正则} else if (obj instanceof Map) {clone = new Map(Array.from(obj, ([key, val]) => [key, deepClone(val, cache)])); // 克隆Map} else if (obj instanceof Set) {clone = new Set(Array.from(obj, val => deepClone(val, cache))); // 克隆Set} else if (Array.isArray(obj)) {clone = []; // 克隆数组} else {clone = Object.create(Object.getPrototypeOf(obj)); // 克隆普通对象(保留原型链)}// 4. 缓存当前对象,防止循环引用cache.set(obj, clone);// 5. 递归拷贝所有属性for (const key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key], cache);}}return clone;
}

方法3:使用现成库(推荐实际开发使用)
  • Lodash
    import _ from 'lodash';
    const deepCopy = _.cloneDeep(original);
    
  • 优点:处理了所有边界情况(函数、循环引用、特殊对象等)。

三、不同场景选择建议

场景推荐方法
简单对象(无函数、日期)JSON.parse(JSON.stringify())
复杂对象(含特殊类型)Lodash 的 cloneDeep
需要手动控制递归克隆实现

总结

  • 浅拷贝:只复制表层,嵌套对象共享。
  • 深拷贝:完全独立副本,彻底隔离。
  • 实际开发:优先使用 Lodash 的 cloneDeep,避免重复造轮子!
http://www.xdnf.cn/news/216811.html

相关文章:

  • 信雅达 AI + 悦数 Graph RAG | 大模型知识管理平台在金融行业的实践
  • C# 类的基本概念(实例成员)
  • 【2024-NIPS-版权】Evaluating Copyright Takedown Methods for Language Models
  • 《云原生》核心内容梳理和分阶段学习计划
  • Alibaba第四版JDK源码学习笔记2025首次开源
  • HCIP【VLAN技术(详解)】
  • Java高频面试之并发编程-11
  • 第三部分:赋予网页灵魂 —— JavaScript(下)
  • Spring Boot - 配置管理与自动化配置进阶
  • 【Bash】可以请您解释性地说明一下“2>1”这个语法吗?
  • Windows 系统下使用 Docker 搭建Redis 集群(6 节点,带密码)
  • C++日更八股--first
  • SpringBoot应用:Docker与Kubernetes全栈实战秘籍
  • git fetch和git pull的区别
  • 域对齐是什么
  • 判断用户选择的Excel单元格区域是否跨页?
  • 力扣hot100——239.滑动窗口最大值
  • 在大数据环境下,使用spingboot为Android APP推送数据方案
  • 【Machine Learning Q and AI 读书笔记】- 02 自监督学习
  • 主流微前端框架比较
  • java面试题目
  • Nacos源码—2.Nacos服务注册发现分析四
  • 三种机器学习类型
  • Glide 如何加载远程 Base64 图片
  • MobileNetV2: 反向残差和线性瓶颈
  • 应急演练考试排查-DC01
  • 【动态导通电阻】GaN功率器件中动态导通电阻退化的机制、表征及建模方法
  • AI 的未来是开源?DeepSeek 正在书写新篇章!
  • 算法基础学习|02归并排序——分治
  • 封装js方法 构建树结构和扁平化树结构