在前端开发中(你平时用 Vue3 + TS,这个问题面试也非常高频),深拷贝是必问知识点。
我给你从 ⭐ 面试级讲解 + ⭐ 实战可用代码 两个层面讲清楚。
一、什么是深拷贝?
const obj = {
name: "chenjie",
info: {
age: 18
}
}
❌ 浅拷贝
const copy = { ...obj }
copy.info.age = 20
console.log(obj.info.age) // 20
👉 内层对象共享引用
✅ 深拷贝
copy.info.age = 20
console.log(obj.info.age) // 18
👉 所有层级都完全复制
二、常见实现方式(面试必答)
1️⃣ JSON 方式(最简单)
const deepClone = (obj) => {
return JSON.parse(JSON.stringify(obj))
}
优点
- 简单
- 够用
缺点(面试加分点)
不能处理:
- undefined
- function
- Symbol
- Date
- RegExp
- Map / Set
- 循环引用
- BigInt
👉 面试时说这几点,基本加分。
2️⃣ structuredClone(现代推荐)
const copy = structuredClone(obj)
优点
- 浏览器原生
- 支持 Map / Set / Date
- 支持循环引用
- 比 JSON 强很多
缺点
- 低版本浏览器不支持
👉 现在新项目优先推荐
3️⃣ 手写递归版本(面试高频)
这是你必须会写的 👇
function deepClone(obj, hash = new WeakMap()) {
if (obj === null) return null
if (typeof obj !== "object") {
return obj
}
// 解决循环引用
if (hash.has(obj)) {
return hash.get(obj)
}
const cloneObj = Array.isArray(obj) ? [] : {}
hash.set(obj, cloneObj)
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], hash)
}
}
return cloneObj
}
三、进阶版(支持 Date、RegExp)
面试中高级一点的写法:
function deepClone(obj, hash = new WeakMap()) {
if (obj === null) return null
if (obj instanceof Date) {
return new Date(obj)
}
if (obj instanceof RegExp) {
return new RegExp(obj)
}
if (typeof obj !== "object") {
return obj
}
if (hash.has(obj)) {
return hash.get(obj)
}
const cloneObj = Array.isArray(obj) ? [] : {}
hash.set(obj, cloneObj)
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = deepClone(obj[key], hash)
}
}
return cloneObj
}
四、Vue 项目中要不要自己写?
⚠️ 在 Vue3 项目里要注意:
- 响应式对象不能随便 JSON
- Proxy 会丢失响应式
如果你只是:
const data = reactive({...})
想要普通对象:
import { toRaw } from "vue"
const raw = toRaw(data)
const copy = structuredClone(raw)
五、面试标准回答模板(你可以直接背)
如果面试官问:
你怎么实现深拷贝?
你可以这样答:
- 简单场景我会用 JSON.parse(JSON.stringify())
- 如果需要支持循环引用、Map、Set,我会用 structuredClone
- 面试手写的话,我会用递归 + WeakMap 解决循环引用
- 生产环境推荐 structuredClone
六、性能对比(面试加分)
一般性能排序:
structuredClone > 手写递归 > JSON
但真实情况取决于数据结构。
七、总结一张表(重点记)
| 方法 | 是否推荐 | 支持循环引用 | 支持Date | 面试 |
|---|---|---|---|---|
| JSON | 简单场景 | ❌ | ❌ | 基础 |
| structuredClone | ⭐⭐⭐⭐ | ✅ | ✅ | 进阶 |
| 手写递归 | ⭐⭐⭐ | ✅ | 可扩展 | 必会 |
如果你愿意,我可以给你:
- ✅ 一份「前端面试高频手写题完整版」
- ✅ 或者带你从源码角度分析 lodash 的 cloneDeep
- ✅ 或者讲讲 Vue 响应式为什么不能随便深拷贝
你想往哪个方向深入?