「一文看懂 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(会报错),不能拷贝 functionsymbolundefined,也无法处理循环引用。
  • 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)) 不能拷贝 functionundefinedsymbol,也会丢失特殊对象。
  4. structuredClone 支持更全,但老浏览器不兼容。

六、总结

  • 浅拷贝 :只复制一层,嵌套对象共用引用。常用 Object.assign、展开运算符等。
  • 深拷贝 :递归复制所有层级,两个对象完全独立。常用 JSON 方法、structuredClone、手写递归。
相关推荐
张迅之21 分钟前
【React】Ant Design 5.x 实现tabs圆角及反圆角效果
前端·react.js·ant-design
@CLoudbays_Martin1123 分钟前
为什么动态视频业务内容不可以被CDN静态缓存?
java·运维·服务器·javascript·网络·python·php
蔗理苦2 小时前
2025-09-05 CSS3——盒子模型
前端·css·css3
二川bro2 小时前
第25节:VR基础与WebXR API入门
前端·3d·vr·threejs
上单带刀不带妹2 小时前
Node.js 的模块化规范是什么?CommonJS 和 ES6 模块有什么区别?
前端·node.js·es6·模块化
缘如风2 小时前
easyui 获取自定义的属性
前端·javascript·easyui
诗书画唱3 小时前
【前端教程】JavaScript 实现图片鼠标悬停切换效果与==和=的区别
开发语言·前端·javascript
光影少年3 小时前
前端上传切片优化以及实现
前端·javascript·掘金·金石计划
喜葵3 小时前
前端安全防护深度实践:从XSS到供应链攻击的全面防御
前端·安全·xss
_r0bin_3 小时前
分片上传-
前端·javascript·状态模式