「一文看懂 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、手写递归。
相关推荐
烬头88218 小时前
React Native鸿蒙跨平台采用了函数式组件的形式,通过 props 接收分类数据,使用 TouchableOpacity实现了点击交互效果
javascript·react native·react.js·ecmascript·交互·harmonyos
Amumu121388 小时前
Vuex介绍
前端·javascript·vue.js
We་ct8 小时前
LeetCode 54. 螺旋矩阵:两种解法吃透顺时针遍历逻辑
前端·算法·leetcode·矩阵·typescript
2601_949809598 小时前
flutter_for_openharmony家庭相册app实战+相册详情实现
javascript·flutter·ajax
qq_177767378 小时前
React Native鸿蒙跨平台通过Animated.Value.interpolate实现滚动距离到动画属性的映射
javascript·react native·react.js·harmonyos
2601_949833399 小时前
flutter_for_openharmony口腔护理app实战+饮食记录实现
android·javascript·flutter
2601_949480069 小时前
【无标题】
开发语言·前端·javascript
css趣多多9 小时前
Vue过滤器
前端·javascript·vue.js
理人综艺好会9 小时前
Web学习之用户认证
前端·学习
●VON9 小时前
React Native for OpenHarmony:项目目录结构与跨平台构建流程详解
javascript·学习·react native·react.js·架构·跨平台·von