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

下面是 下一道高频前端面试题(第 17 题:深拷贝与浅拷贝)

继续保持:详细版 + 速记卡片


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

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


📘 一、浅拷贝(Shallow Copy)

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

常见浅拷贝方式:

1)Object.assign()

ini 复制代码
const obj = { a:1, b:{ c:2 } }
const copy = Object.assign({}, obj)

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

2)扩展运算符 ...

go 复制代码
const copy = { ...obj }

3)Array.prototype.slice / concat

ini 复制代码
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())

ini 复制代码
const obj = { a:1, b:{ c:2 } }
const copy = JSON.parse(JSON.stringify(obj))

👍 优点:简单、常用

⚠️ 缺点:

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

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

ini 复制代码
const clone = structuredClone(obj)

👍 支持:

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

⚠️ 不支持 function


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

go 复制代码
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

go 复制代码
const copy = _.cloneDeep(obj)

👍 稳定,功能完备

⚠️ 项目里不一定允许使用


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

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

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

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

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

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

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

相关推荐
前端一课1 小时前
【前端每天一题】🔥 第 20 题:从输入 URL 到页面渲染全过程
前端·面试
前端一课1 小时前
【前端每天一题】🔥 第 12 题:== 与 === 的区别?为什么 [] == ![] 是 true?
前端·面试
前端一课1 小时前
【前端每天一题】🔥 第 13 题:原型链查找规则是什么?为什么对象能访问到方法?
前端·面试
前端一课1 小时前
【前端每天一题】🔥 第 11 题:this 的指向规则(前端高频必考题)
前端·面试
一 乐1 小时前
餐厅管理智能点餐系统|基于java+ Springboot的餐厅管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·spring boot·后端
北极糊的狐1 小时前
父组件向子组件传参时,传递数组和对象类型的参数的方法
前端·javascript·vue.js
前端一课1 小时前
【前端每天一题】🔥 第 9 题:防抖(debounce)与节流(throttle)的区别?如何实现?
前端·面试
前端一课2 小时前
【前端每天一题】🔥 第 10 题:浅拷贝 vs 深拷贝?如何手写深拷贝?
前端·面试
前端一课2 小时前
【前端每天一题】🔥 第 8 题:什么是事件委托?它的原理是什么?有哪些优点和常见坑? - 前端高频面试题
前端·面试