• JavaScript -- 多种数组深拷贝和浅拷贝的方法的总结


    数组的拷贝

    复制是复制出来一个新的对象,二者指向的是不同的对象,直接采用等号赋值的话二者指向的是同一个对象

    也可以修改某个元素,看看另一个数组中的元素会不会被修改掉

    const arr = ["孙悟空", "猪八戒", "沙和尚"]
    const arr2 = arr  // 不是复制,二者指向的是同一个对象
    
    console.log(arr === arr2)	// true
    
    • 1
    • 2
    • 3
    • 4

    这种情况内存图如下

    image-20221202200648484

    1 slice()拷贝

    当调用slice时,会产生一个新的数组对象,从而完成对数组的复制

    const arr = ["孙悟空", "猪八戒", "沙和尚"]
    const arr3 = arr.slice()
    
    console.log(arr === arr3)	// false
    
    • 1
    • 2
    • 3
    • 4

    2 new Array()拷贝

    也可以使用new Array()产生新对象

    const arr = ["孙悟空", "猪八戒", "沙和尚"]
    const arr4 = new Array(arr)
    
    console.log(arr === arr4)	// false
    
    • 1
    • 2
    • 3
    • 4

    3 浅拷贝和深拷贝

    https://www.bilibili.com/video/BV1mG411h7aD?p=95

    浅拷贝(shallow copy)

    • 通常对对象的拷贝都是浅拷贝
    • 浅拷贝顾名思义,只对对象的浅层进行复制(只复制一层)
    • 如果对象中存储的数据是原始值,那么拷贝的深浅是不重要
    • 浅拷贝只会对对象本身进行复制,不会复制对象中的属性(或元素)
    • 使用slice()或者new Array(arr)进行浅拷贝

    深拷贝(deep copy)

    • 深拷贝指不仅复制对象本身,还复制对象中的属性和元素
    • 因为性能问题,通常情况不太使用深拷贝
    • 使用structuredClone(arr)进行深拷贝

    例如定义如下数组,其在内存图中情况如图:

    image-20221202201252027

    使用slice()进行浅拷贝,从图中看出来只复制了第一层,并没有复制元素中的属性

    image-20221202201355793

    在此时,通过代码进行验证,可以看出两个数组指向不一样,但是其中的对象是共享的,所以修改一个另一个也会发生改变:

    image-20221202201607828

    深拷贝内存情况如图,不止复制了元素,也复制了元素里面的属性:

    image-20221202201819232

    对于如下代码和结果也可以验证结果:

    const arr = [{name:"孙悟空"}, {name:"猪八戒"}]
    const arr2 = arr.slice() // 浅拷贝
    
    const arr3 = structuredClone(arr) // 专门用来深拷贝的方法
    
    console.log(arr)
    console.log(arr3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    image-20221202215845329

    4 展开运算符

    展开运算符:...

    • 可以将一个数组中的元素展开到另一个数组中或者作为函数的参数传递
    • 通过它也可以对数组进行浅复制
    const arr = ["孙悟空", "猪八戒", "沙和尚"]
    const arr3 = [...arr]
    
    arr === arr3 // false
    
    • 1
    • 2
    • 3
    • 4

    这种方式得到的也是浅拷贝

    除此之外,还可以把参数展开

    function sum(a, b, c) {
        return a + b + c
    }
    
    const arr4 = [10, 20, 30]
    
    let result1 = sum(arr4[0], arr4[1], arr4[2])
    let result2 = sum(...arr4)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5 对象的复制

    • Object.assign(目标对象, 被复制的对象)

    • 将被复制对象中的属性复制到目标对象里,并将目标对象返回

    • 也可以使用展开运算符对对象进行复制

    const obj = { name: "孙悟空", age: 18 }
    
    // 方法一:复制到空对象后获取返回值
    const obj2 = Object.assign({}, obj)
    console.log(obj2)
    
    // 方式二:直接复制到一个对象中,不会改变原有属性
    const obj3 = { address: "花果山", age: 28 }
    Object.assign(obj3, obj)
    console.log(obj3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    image-20221202220805245

    也可以使用展开运算符

    const obj3 = { address: "高老庄", ...obj, age: 48 } // 将obj中的属性在新对象中展开
    
    • 1

    image-20221202221047064

    6 使用JSON进行深拷贝

    const obj = {
        name: "孙悟空",
        friend: {
            name: "猪八戒",
        },
    }
    
    // 对obj进行浅复制
    const obj2 = Object.assign({}, obj)
    
    // 对obj进行深复制
    const obj3 = structuredClone(obj)
    
    // 利用JSON来完成深复制
    const str = JSON.stringify(obj)
    const obj4 = JSON.parse(str)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    vue学习总结
    @Scheduled定时任务参数解释
    Linux操作系统
    ABAP 设置开票后不允许修改采购订单价格
    【Linux】进程间通信介绍及匿名管道使用
    Go:微服务架构下的单元测试(基于 Ginkgo、gomock 、Gomega)
    class的get和set
    纯血鸿蒙APP实战开发——阅读翻页方式案例
    制造企业发展遇瓶颈?低代码平台助其逆风翻盘!
    ​软考-高级-系统架构设计师教程(清华第2版)【第18章 安全架构设计理论与实践(P648~690)-思维导图】​
  • 原文地址:https://blog.csdn.net/qq_46311811/article/details/128207487