news 2026/10/15 4:54:07

当JS拷贝玩起了“俄罗斯套娃”:深拷贝与浅拷贝的趣味对决

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
当JS拷贝玩起了“俄罗斯套娃”:深拷贝与浅拷贝的趣味对决

欢迎使用我的小程序👇👇👇👇 俱好用助手功能介绍


📚 拷贝不只是复制粘贴

想象一下,你有一本心爱的精装书,朋友想借去阅读。你有两个选择:

  1. 直接给朋友- 但书就不在你手上了(原始引用)
  2. 去复印店复印一本- 朋友有自己的副本,你的原版还在

在JavaScript的世界里,拷贝数据就像这个场景,但有更多的“套娃”情况!

🎭 浅拷贝:只搬家的“表面朋友”

浅拷贝就像只搬走了家具,但墙上还挂着原房子的钥匙:

// 原始对象 - 一个“套娃”对象constoriginal={name:"小明",age:25,hobbies:["编程","游戏","阅读"],// 注意这个数组!address:{city:"北京",district:"海淀区"}};// 浅拷贝的几种方式:constshallowCopy1=Object.assign({},original);constshallowCopy2={...original};// 扩展运算符constshallowCopy3=original.slice?.();// 数组专用// 试试修改会发生什么?shallowCopy1.name="小红";// ✅ 不会影响originalshallowCopy1.hobbies.push("摄影");// ⚠️ 糟糕!original的hobbies也被改了!

浅拷贝的特点:

  • 只复制第一层属性
  • 嵌套对象/数组仍然是“共享”的引用
  • 像只换了外壳,芯子还是同一个

🧳 深拷贝:真正的“独立门户”

深拷贝就像带着所有家当搬到了全新的房子:

// 深拷贝实现方式大比拼// 方法1:JSON大法(最简单但有局限)constdeepCopy1=JSON.parse(JSON.stringify(original));// 方法2:递归实现(自己动手,丰衣足食)functiondeepClone(obj){if(obj===null||typeofobj!=='object')returnobj;if(objinstanceofDate)returnnewDate(obj);if(objinstanceofRegExp)returnnewRegExp(obj);constclone=Array.isArray(obj)?[]:{};for(letkeyinobj){if(obj.hasOwnProperty(key)){clone[key]=deepClone(obj[key]);}}returnclone;}constdeepCopy2=deepClone(original);// 方法3:使用现成库(最省心)// const deepCopy3 = _.cloneDeep(original); // Lodash// const deepCopy4 = structuredClone(original); // 现代JS原生API

现在无论怎么修改deepCopy,都不会影响original了!

🎯 什么时候用什么?

浅拷贝适用场景:

// 场景1:配置合并constdefaultConfig={theme:'light',showTips:true};constuserConfig={theme:'dark'};constfinalConfig={...defaultConfig,...userConfig};// 场景2:创建对象副本进行简单修改constuser={name:'张三',loggedIn:false};constupdatedUser={...user,loggedIn:true};

深拷贝适用场景:

// 场景1:状态管理(如Redux reducer)functionreducer(state,action){switch(action.type){case'UPDATE_USER':return{...state,user:deepClone(action.payload)// 确保完全独立};}}// 场景2:表单数据的初始副本constinitialFormData=deepClone(templateData);constformData=deepClone(initialFormData);// 每次都是新的开始

🧪 趣味实验:拷贝的陷阱

// 陷阱1:循环引用(自己引用自己)constnarcissist={name:"自恋对象"};narcissist.self=narcissist;// 我引用我自己!// JSON大法会报错!// JSON.parse(JSON.stringify(narcissist)); // TypeError!// 陷阱2:特殊对象constspecialObj={date:newDate(),regex:/hello/gi,func:function(){return"Hi";},undefined:undefined,infinity:Infinity,nan:NaN};console.log(JSON.parse(JSON.stringify(specialObj)));// 函数、undefined不见了!日期变成了字符串...

📊 性能对比:速度与深度的博弈

方法速度深度特殊类型支持循环引用支持
扩展运算符...⚡⚡⚡⚡⚡浅有限❌
Object.assign()⚡⚡⚡⚡⚡浅有限❌
JSON方法⚡⚡⚡深差❌
递归实现⚡⚡深好❌
Lodash的cloneDeep⚡⚡深很好✅
structuredClone()⚡⚡⚡深较好✅

💡 实用小贴士

  1. “先问要不要,再问怎么做”- 先确定是否需要深拷贝,很多情况浅拷贝就够用了

  2. 现代JS的救星:

    // 浏览器和Node.js的新宠constcloned=structuredClone(original);// 支持大部分类型!
  3. Lodash是你的好朋友:

    import{cloneDeep}from'lodash-es';// 按需引入// 或者用 throttle 的深拷贝函数
  4. 性能提示:对于超大对象,考虑是否需要整个拷贝,也许只需修改部分

🎬 实战演练:拷贝在真实场景的应用

// 购物车场景constshoppingCart={items:[{id:1,name:"JavaScript高级编程",quantity:1,price:99},{id:2,name:"TypeScript入门",quantity:2,price:79}],discount:0.1,getTotal(){returnthis.items.reduce((sum,item)=>sum+item.price*item.quantity,0)*(1-this.discount);}};// 用户想“如果这样买”的试算功能functionwhatIfAddItem(cart,newItem){consthypotheticalCart=deepClone(cart);hypotheticalCart.items.push(newItem);returnhypotheticalCart.getTotal();}// 真实的购物车不受影响console.log(shoppingCart.items.length);// 还是2个

📝 总结:拷贝选择指南

  1. “我只想改改表面”→ 用浅拷贝(...或Object.assign)
  2. “我要完全独立的新对象”→ 用深拷贝
  3. “我有特殊类型或循环引用”→ 用structuredClone()或Lodash
  4. “不确定深浅”→ 问问自己:嵌套对象需要独立吗?

记住,在JavaScript的世界里,“拷贝”不是简单的复制粘贴,而是关于“独立性”的哲学选择。选择正确的拷贝方式,能让你的代码更健壮、更可预测!

下次当你面对需要拷贝的场景时,不妨先想想:这是一个需要独立门户的深拷贝,还是一个可以共享芯子的浅拷贝?


✨小测验:你能看出下面代码的输出吗?

constobj={a:1,b:{c:2}};constshallow={...obj};constdeep=JSON.parse(JSON.stringify(obj));shallow.b.c=999;deep.b.c=888;console.log(obj.b.c);// 是多少?

答案:999,因为浅拷贝共享了嵌套对象!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 0:21:53

振动下的安全防线:ASTM D999如何守护新能源电池运输命脉

随着全球新能源产业蓬勃发展,锂离子电池等新能源产品在运输环节的安全问题日益凸显。ASTM D999-08(2023)《船运集装箱振动测试的标准测试方法》作为国际通用的包装测试规范,为新能源电池的安全运输提供了科学依据和技术支撑,其重要性不容忽视…

作者头像 李华
网站建设 2026/10/15 7:36:38

医疗产品运输安全:ISTA 3A标准应用

在医疗行业,产品从生产到患者手中的安全旅程至关重要。尤其对于生物医药制品和医疗器械,一次不当的运输可能导致产品失效,甚至危及患者生命。ISTA 3A标准作为国际公认的产品运输包装验证体系,为医疗行业提供了科学的测试框架。医疗…

作者头像 李华
网站建设 2026/10/15 12:19:58

AI Agent上线前必须检查的7项文档指标,少一项都可能崩溃

第一章:AI Agent上线前文档检查的重要性在将AI Agent部署到生产环境之前,系统化的文档检查是确保其稳定性、合规性和可维护性的关键环节。完整的文档不仅能帮助开发团队快速定位问题,还能为后续的审计、升级和知识传递提供坚实基础。确保接口…

作者头像 李华
网站建设 2026/10/15 16:01:21

地方2000坐标系的dwg如何导入Cesium

大家好,上一篇我们介绍了如何在Cesium当中导入标准的高斯克吕格投影的坐标系,我们先回忆一下上一篇中说道的DWG坐标系的三种情况: 1.国家2000坐标系 2.地方2000坐标系 3.没有对应位置信息的局部坐标系 我们已经看了第一种情况&#xff0c…

作者头像 李华
网站建设 2026/10/14 19:17:33

99% 的医疗 AI 项目忽视的隐私漏洞,你中招了吗?

第一章:医疗 AI 中隐私泄露的隐形危机在人工智能加速渗透医疗领域的当下,AI 模型通过分析电子病历、医学影像和基因数据显著提升了诊断效率。然而,这些高度敏感信息的集中处理也带来了严重的隐私风险。一旦模型训练或推理过程中缺乏有效的隐私…

作者头像 李华
网站建设 2026/10/15 0:59:43

多 Agent 系统在自动驾驶中的应用(融合架构设计与实战案例)

第一章:自动驾驶中多 Agent 融合架构的演进与挑战随着自动驾驶技术的发展,系统复杂度迅速提升,单一决策模型已难以应对城市开放环境中的动态交互场景。多 Agent 融合架构应运而生,通过将感知、规划、控制等模块解耦为多个协同工作…

作者头像 李华