前端中浅拷贝 vs 深拷贝,一次就懂!

177 阅读5分钟

🌊 一次搞懂前端中的浅拷贝与深拷贝(附实战案例)

在前端开发中,有没有遇到过这种“离谱”的情况:

“我明明复制了一个对象,结果改了副本,原来的也跟着变了!”

这并不是 JavaScript 的 bug,而是你被“浅拷贝”坑了。

别慌——今天我们就用最通俗的语言,一次性搞清楚这些看起来拗口的概念:
深拷贝、浅拷贝、深克隆、浅克隆、深复制、浅复制

其实,它们都围绕一个核心问题:对象到底是复制值,还是复制引用?


🧠 一、什么是“拷贝”?

在 JS 中,变量分为两大类:

  • 基本类型(如 number、string、boolean)
    → 存的是值,复制时也只是把值复制过去。
  • 引用类型(如 object、array、function)
    → 存的是“地址”,复制时其实是复制地址。
    两个变量指向同一块内存。

所以,如果你修改了其中一个对象的内容,另一个也会被影响。
这就是为什么有时候你“复制了对象”,但改副本时,原来的数据也变了。


💧 二、浅拷贝(Shallow Copy)

✅ 定义

浅拷贝只复制对象的第一层属性
如果属性的值是对象或数组,那么拷贝的只是“引用地址”。

🧩 举个例子

const obj1 = {
  name: "小明",
  info: {
    age: 18
  }
};

const obj2 = { ...obj1 }; // 浅拷贝
obj2.info.age = 20;

console.log(obj1.info.age); // 输出 20 —— 原对象也被改了!

因为 obj2.infoobj1.info 指向同一块内存空间。
你改了其中一个,另一个当然也会变。

⚙️ 常见浅拷贝方法

  • Object.assign({}, obj)
  • 展开语法 { ...obj }
  • Array.prototype.slice()
  • Array.prototype.concat()

📌 适用场景:
结构简单、数据层级不深的对象或数组。
优点是性能高、速度快;缺点是容易误改原数据


🔥 三、深拷贝(Deep Copy)

✅ 定义

深拷贝会把对象的所有层级都复制一份,生成一个全新的对象。
修改新对象不会影响原来的数据。

🧩 举个例子

const obj1 = {
  name: "小明",
  info: {
    age: 18
  }
};

const obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝
obj2.info.age = 20;

console.log(obj1.info.age); // 输出 18 ✅ 原对象没变

⚙️ 常见深拷贝方式

方法优点缺点
JSON.parse(JSON.stringify(obj))简单、通用无法拷贝函数、Symbol、undefined
structuredClone(obj)原生支持、功能强仅现代浏览器支持
lodash.cloneDeep(obj)稳定、兼容性好需安装第三方库

🌟 推荐方式(现代项目)

const newObj = structuredClone(oldObj);

这是浏览器原生支持的深拷贝方案,
既高效又能处理复杂结构(如 Date、Map、Set)。


⚔️ 四、实战案例:浅拷贝踩坑 vs 深拷贝救场

来看一个开发中经常遇到的“真实事故”。

💥 场景:Vue 或 React 状态被意外修改

const students = [
  { name: "小明", age: 18 },
  { name: "小红", age: 17 }
];

// ❌ 浅拷贝数组
const copyStudents = [...students];
copyStudents[0].age = 20;

console.log(students[0].age); // 输出 20 —— 原数据也被改了!

问题出在哪?
因为展开语法 [...] 只拷贝了外层数组,
内部的对象依旧共用引用地址。

这在前端框架中非常危险:
如果你在 Vue 或 React 的状态中这样操作,
可能导致页面错误刷新、状态错乱


✅ 正确做法:深拷贝来救场

// 推荐方法 1
const deepCopy = structuredClone(students);

// 或者方法 2
const deepCopy = JSON.parse(JSON.stringify(students));

deepCopy[0].age = 20;

console.log(students[0].age); // 输出 18 ✅ 原数据安全
console.log(deepCopy[0].age); // 输出 20 ✅ 新数据独立

这样,深拷贝就彻底解决了“连带修改”的问题。
数据独立、状态安全,前端程序员终于能安心睡觉了 😄。


🔍 实战结论

拷贝方式是否影响原始数据推荐场景
浅拷贝会影响原数据简单结构、性能优先
深拷贝不会影响原数据状态管理、复杂嵌套

🧩 五、拷贝、复制、克隆有区别吗?

其实在前端中,这几个词的意思几乎一样。

名称英文含义
拷贝copy复制数据
复制duplicate一般语言描述
克隆clone程序员更偏爱用的说法 😎

真正需要区分的只有两个字:浅 vs 深。


🚀 六、为什么要区分深浅拷贝?

因为这会直接影响到前端应用的稳定性。

在组件状态管理中(如 React 的 useState 或 Vue 的 reactive):

  • 如果只是浅拷贝,修改副本会污染原始状态;
  • 深拷贝则能保证每一份数据都相互独立。

一句话总结:

深拷贝是“保险”,浅拷贝是“捷径”。
开发中需要根据数据结构和性能需求灵活选择。


📊 七、深浅拷贝对比一览

类型拷贝层级是否共享引用常用方法适用场景
浅拷贝第一层Object.assign、{...obj}简单数据、性能优先
深拷贝所有层级structuredClone、cloneDeep状态管理、复杂对象

💡 八、一句话总结

  • 浅拷贝:只复制一层,里面的对象“合租”;
  • 深拷贝:复制到底,里面的对象“买房独住”。

🔁 九、快速回顾

  1. “拷贝”、“复制”、“克隆”其实是一回事;
  2. 关键在于是“浅”还是“深”;
  3. 浅拷贝快但不安全;
  4. 深拷贝稳但稍慢;
  5. 推荐使用 structuredClone()

🌈 十、写在最后

深浅拷贝看似是一个小细节,却是每个前端工程师必须理解的基础。
它直接关系到数据安全、状态管理、组件通信等核心逻辑。

正所谓:

能搞懂拷贝的人,写出的代码更干净、Bug更少。

所以,记住这句话:

该深就深,该浅就浅,复制要有分寸。


作者:CrabXin
时间:2025年10月
标签:前端开发 / JavaScript / 深拷贝 / 浅拷贝