【前端每天一题】🔥 第 17 题:什么是浅拷贝与深拷贝?如何实现深拷贝?

101 阅读2分钟

下面是 下一道高频前端面试题(第 17 题:深拷贝与浅拷贝)
继续保持:详细版 + 速记卡片


✅ 第 17 题:什么是浅拷贝与深拷贝?如何实现深拷贝?

这是前端必考题,答案必须结构化、带例子。


📘 一、浅拷贝(Shallow Copy)

只复制第一层属性,对象内嵌的对象仍然引用同一个地址。

常见浅拷贝方式:

1)Object.assign()

const obj = { a:1, b:{ c:2 } }
const copy = Object.assign({}, obj)

copy.b.c = 999
console.log(obj.b.c) // 999,被影响

2)扩展运算符 ...

const copy = { ...obj }

3)Array.prototype.slice / concat

const arr = [1, {x:2}]
const copy = arr.slice()
copy[1].x = 999
console.log(arr[1].x) // 999

结论:浅拷贝只复制第一层,嵌套对象仍共享引用。


📘 二、深拷贝(Deep Copy)

将所有层级的数据复制,不共享引用。


📘 三、深拷贝方法大全


🚀 方法 1:JSON.parse(JSON.stringify())

const obj = { a:1, b:{ c:2 } }
const copy = JSON.parse(JSON.stringify(obj))

👍 优点:简单、常用
⚠️ 缺点:

  • 无法拷贝 function
  • 无法拷贝 undefined
  • 无法拷贝 symbol
  • 无法处理循环引用

🚀 方法 2:结构化克隆(现代浏览器最推荐)

const clone = structuredClone(obj)

👍 支持:

  • Date / RegExp
  • Map / Set
  • 深层嵌套
  • 循环引用

⚠️ 不支持 function


🚀 方法 3:手写深拷贝(必会面试代码)

function deepClone(obj, map = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj

  if (map.has(obj)) return map.get(obj)

  const copy = Array.isArray(obj) ? [] : {}
  map.set(obj, copy)

  for (let key in obj) {
    copy[key] = deepClone(obj[key], map)
  }
  return copy
}

const newObj = deepClone(oldObj)

👍 能力最强:可以处理循环引用 + 深层结构
⚠️ 不处理 function / Symbol 需要额外补强


🚀 方法 4:第三方库 Lodash.cloneDeep

const copy = _.cloneDeep(obj)

👍 稳定,功能完备
⚠️ 项目里不一定允许使用


📘 四、浅拷贝 vs 深拷贝 总结表

对比点浅拷贝深拷贝
是否复制所有层级?❌ 否✅ 是
是否共享引用?✅ 是❌ 否
常见方法Object.assign / ...JSON / structuredClone / 手写递归
性能相对慢
是否能处理循环引用❌ 否structuredClone / 手写可处理

📘 五、速记卡片(面试背诵版)

🎯浅拷贝:只复制第一层,嵌套对象共用引用
- Object.assign
- 扩展运算符 ...
- slice / concat

🎯深拷贝:复制所有层级,不共享引用
- JSON.parse(JSON.stringify()) → 快速但有限
- structuredClone() → 最强官方方案
- 手写 deepClone() → 面试必会
- lodash.cloneDeep → 工程可用

核心:深拷贝要解决循环引用 + 各种类型处理

第 18 题将是:防抖(debounce)与节流(throttle)区别与实现。