JS 拷贝的"分身术":深拷贝 vs 浅拷贝

在 JavaScript 中,因为对象和数组是引用类型,所以当我们直接将它们赋值给另一个变量时,实际上是将它们的引用地址复制了一份。这样,当我们对其中一个变量进行修改时,另一个变量也会受到影响。因此,为了避免这种情况,我们通常需要使用拷贝方法来复制一个对象或数组的值并创建一个新的副本。本文将来介绍浅拷贝和深拷贝的概念以及它们的应用场景

浅拷贝

定义:浅拷贝只复制对象的第一层属性,如果属性是基本类型,则赋值其值;如果是引用类型则赋值其内存地址

特点:

  • 新对象和原对象共享引用类型的属性
  • 修改拷贝对象的引用类型属性会影响原对象
  • 实现简单,性能较好

浅拷贝常见实现方法

1、Object.create(obj)

Object.create() 方法可以用于创建一个新对象,并将原对象作为新对象的原型。这样,新对象就可以访问原对象的所有属性和方法

js 复制代码
const obj1 = { name: '张三', age: 18 };
const obj2 = Object.create(obj1);
console.log(obj2.name); // 张三

obj1.name = '李四'
console.log(obj2.name); //李四

2、Object.assign({},obj)

Object.assign({}, obj) 是实现对象浅拷贝的标准方法,它通过将源对象的可枚举属性复制到目标对象(这里是空对象 {})来实现拷贝。

js 复制代码
const originalObj = { a: 1, b: { c: 2 } };
const copiedObj = Object.assign({}, originalObj);

console.log(copiedObj); // { a: 1, b: { c: 2 } }
console.log(copiedObj === originalObj); // false (新对象)

3、\[\].concat(arr)

[].concat(arr) 是实现数组浅拷贝的一种传统方法,它通过连接空数组和目标数组来创建一个新数组。

js 复制代码
const arr = [1, 2, 3];
const newArr = [].concat(arr);

console.log(newArr); // [1, 2, 3]
console.log(newArr === arr); // false (是不同的数组实例)

4、...arr

[...arr] 是 ES6 引入的展开运算符(Spread Operator) 用于数组的浅拷贝,这是现代 JavaScript 中最简洁的数组浅拷贝方式之一。

js 复制代码
const originalArr = [1, 2, 3];
const copiedArr = [...originalArr];

console.log(copiedArr); // [1, 2, 3]
console.log(copiedArr === originalArr); // false (新数组)

5、arr.slcie()

arr.slice() 是 JavaScript 数组的一个内置方法,用于创建数组的浅拷贝(shallow copy) 。

js 复制代码
const arr = [1, 2, 3];
const newArr = arr.slice();
console.log(newArr);//[1,2,3]
console.log(newArr === arr); // false (是新数组)

深拷贝

定义:深拷贝会递归复制对象的所有层级,创建一个完全独立的副本,新旧对象不会共享任何引用。

特点:

  • 无论修改原始对象的顶层还是嵌套子对象,均不会影响拷贝后的对象
  • 需要更多内存和计算资源(尤其是复杂对象)

深拷贝常见实现方法

1、JSON.parse(JSON.stringify())

JSON.parse(JSON.stringify())是最简单的深拷贝实现方法但其有局限性,无法处理undefined、function、Symbol、Date、RegExp、Map、Set 等。

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

obj.b.c = 99;
console.log(deepCopy.b.c); // 输出 2(未被修改)

2、structuredClone() structuredClone()是浏览器和Node.js提供的原生深拷贝方案比JSON.parse(JSON.stringify())更强大且安全。

js 复制代码
const obj = { a: 1, b: new Date(), c: new Set([1, 2]) };
const deepCopy = structuredClone(obj);

obj.c.add(3);
console.log(deepCopy.c); // 输出 Set { 1, 2 }(未被修改)

浅拷贝和深拷贝关键区别

关键区别总结

特性 浅拷贝 深拷贝
复制层级 仅顶层 所有嵌套层级
子对象引用 共享(指向同一内存地址) 独立(新内存地址)
性能 快 慢(递归复制)
适用场景 简单对象 需要完全隔离的复杂对象

面试题:手搓一个深浅拷贝

浅拷贝:

js 复制代码
let obj = {
    name: '困困',
    age: 18,
    like: {
        a: '唱',
        b: '跳',
        c: 'rap'
    }
}
function shallowCopy(obj) {
    let newObj = {}
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) { //判断key是不是obj显示拥有的
            newObj[key] = obj[key]
        }
    }
    return newObj
}
console.log(shallowCopy(obj))

深拷贝

js 复制代码
    let obj = {
        name: '困困',
        age: 18,
        like: {
            a: '唱',
            b: '跳',
            c: 'rap'
        }
    }
    function deepCopy(obj) {
        let newObj = {}
        for (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
    }
    let obj2=deepCopy(obj)
    console.log(obj2)
相关推荐
结局无敌3 分钟前
React Native for OpenHarmony 实战:三方库 react-native-paper 的鸿蒙化适配指南
javascript·人工智能·深度学习·react native·react.js·ecmascript·harmonyos
铁皮饭盒18 分钟前
CPU就行, 老照片变清晰, 本地部署582mb腾讯的模型, 本地部署, 过节了给长辈们变个小魔术
前端·javascript·后端
结局无敌44 分钟前
React Native for OpenHarmony 实战:三方库 react-native-progress-steps 的鸿蒙化适配指南
javascript·人工智能·深度学习·react native·react.js·harmonyos
tryCbest1 小时前
第三篇:JavaScript 基础语法全解 + TaskFlow 逻辑实现
javascript·前端知识
after you1 小时前
【无标题】
前端·javascript
酷炫码神1 小时前
Day 6|ES6+ 语法:把现代 JS 写顺手,从解构到 map / filter / reduce
前端·javascript·es6
studyForMokey1 小时前
【Android 面试】Paging3
android·面试·职场和发展
考研保研资料分享2 小时前
211英语专业跨保清华法学:2022年法学面试与口译考核复盘
面试·职场和发展
晓得迷路了2 小时前
栗子前端技术周刊第 150 期 - Stack Overflow 开发者调查结果、TanStack Start 1.0...
javascript·css·后端
考研保研资料分享2 小时前
2024双非材料保研复旦:五校面试题与科研复盘
面试·职场和发展