「一文看懂 JS 深浅拷贝,彻底告别面试踩坑!」

在 JavaScript 开发中,深浅拷贝是一个绕不开的话题。无论是日常开发还是面试,拷贝对象的方式和原理都经常被问到。本文将用最简明的语言,结合实例,帮你彻底搞懂深浅拷贝的核心概念和常见实现方式,助你轻松应对各种场景!


一、什么是拷贝?为什么要拷贝?

拷贝,就是复制一个对象,让新对象和原对象"长得一模一样"。

但"复制"分为两种:浅拷贝和深拷贝。

  • 浅拷贝:只复制第一层属性,如果属性是引用类型(如对象、数组),复制的是"引用地址"。
  • 深拷贝:递归复制所有层级,嵌套对象也会被完整复制,新旧对象互不影响。

为什么要拷贝呢?

在 JS 中,为了避免直接修改原数据带来的副作用。这时候我们就需要复制这个对象,来操作复制的对象


二、JS 中的数据类型

理解拷贝,先要知道 JS 的数据类型:

  • 基本类型:number、string、boolean、null、undefined、symbol、bigint(存储在栈内存)
  • 引用类型:object、array、function、date、regexp 等(存储在堆内存)

基本类型直接存值,引用类型存的是"地址"。


三、浅拷贝:复制表面,引用共享

1. 常见实现方式

  • Object.assign({}, obj)
  • 数组解构 [...arr]
  • arr.slice()
  • [].concat(arr)
  • Object.create(obj)

2. 例子说明

假设有如下对象:

js 复制代码
const obj1 = {
  name: "小华",
  info: { age: 18 }
};
const obj2 = Object.assign({}, obj1);
obj2.name = "小鱼";
obj2.info.age = 20;
console.log(obj1); // { name: "小华", info: { age: 20 } }

解释 :
name 是基本类型,修改 obj2.name 不影响 obj1。
info 是对象,浅拷贝只复制了引用,obj2.info.age 改变会影响 obj1.info.age。

3. 适用场景

  • 只需要复制一层属性
  • 不关心嵌套对象是否联动

四、深拷贝:彻底分离,互不影响

1. 常见实现方式

  • JSON.parse(JSON.stringify(obj))
    简单粗暴,但有缺陷:不能识别 bigin(会报错),不能拷贝 function、symbol、undefined,也无法处理循环引用。
  • structuredClone(obj)
    新标准,支持更多类型,但兼容性有限。
  • 手写递归深拷贝(见下文)

2. 例子说明(JSON.parse(JSON.stringify(obj)))

js 复制代码
const obj1 = {
  name: "小华",
  info: { age: 18 }
};
const obj2 = JSON.parse(JSON.stringify(obj1));
obj2.info.age = 20;
console.log(obj1); // 

解释 :
obj2 完全独立,修改嵌套属性不会影响 obj1。

3. 手写深拷贝(递归拷贝)

实现如下:

js 复制代码
function deepCopy(obj) {
    let newObj = {}
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            // 先判断 obj[key] 值的类型
            if (typeof obj[key] === 'object' && obj[key] !== null) { // 如果是对象
                newObj[key] = deepCopy(obj[key])
            } else {  // 如果不是对象
                newObj[key] = obj[key]
            }
        }
    }
    return newObj
}

用法举例:

js 复制代码
const arr1 = [1, 2, { a: 3 }];
const arr2 = deepClone(arr1);
arr2[2].a = 100;
console.log(arr1); // [1, 2, { a: 3 }]

改变了 arr2 中 {a: 3} 的值,但是原数组 arr1 的值不变。

五、常见误区与注意点

  1. 浅拷贝只复制一层,嵌套对象还是"共用"。
  2. 深拷贝要递归,但要注意循环引用、特殊类型(如 Date、函数等)。
  3. JSON.parse(JSON.stringify(obj)) 不能拷贝 function、undefined、symbol,也会丢失特殊对象。
  4. structuredClone 支持更全,但老浏览器不兼容。

六、总结

  • 浅拷贝 :只复制一层,嵌套对象共用引用。常用 Object.assign、展开运算符等。
  • 深拷贝 :递归复制所有层级,两个对象完全独立。常用 JSON 方法、structuredClone、手写递归。
相关推荐
明月_清风4 小时前
Deno 终局来了:从挑战 Node 到被 Cloudflare 收编
前端·后端·node.js
Csvn5 小时前
框架性能优化
前端
回眸&啤酒鸭7 小时前
【回眸】OpenSwarm 多智能体协作系统实战指南
大数据·前端·人工智能
用户69371750013847 小时前
2026,程序员的时代拐点到了
android·前端·后端
大龄秃头程序员7 小时前
一次 iBeacon + BLE 无感解锁方案的实现记录
前端
小兔子7 小时前
Python 的 GIL 与 free-threading:3.13 之后「去 GIL」走到哪一步了
前端
IT_陈寒7 小时前
SpringBoot自动配置差点让我加班到凌晨
前端·人工智能·后端
guslegend9 小时前
脚手架原理与本地调试:从 bin 软链接到 npm link
前端·npm·node.js·脚手架·前端工程化
小宋10219 小时前
A2UI从零实战:Agent安全生成交互界面与事件回传
javascript·人工智能·安全·交互
大包子9 小时前
structuredClone vs lodash.cloneDeep:核心差异与选型指南
javascript·vue.js