深拷贝 & 浅拷贝

592 阅读2分钟

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战

前言

拷贝数据是很常见和常规的操作,但有些时候实现起来会和预期的不符

文章比较简单,更希望一边观看一边尝试

基础类型 & 引用类型

基础类型

  1. String
  2. Number
  3. ...

引用类型

  1. Object
  2. Array

堆 & 栈

  1. 动态分配内存
  2. 内存大小不固定
  3. 不会自动释放内存

  1. 自动分配内存空间
  2. 系统自动释放内存

浅拷贝

基础类型单独管理,引用类型共用同一个地址

Object.assign()

let obj1 = {
    a: 1,
    b: [1, 2]
}

let obj2 = Object.assign({}, obj1)

obj1.a = 2
obj1.c[0] = 2

console.log(obj1) // { a: 2, b: [2, 2] }
console.log(obj2) // { a: 1, b: [2, 2] }

修改 obj1 基础类型没变化,但是引用类型改变了

扩展运算符 ...

let arr1 = [1, [1, 2]]
let arr2 = [...arr1]
let arr3 = [].concat(arr1)

arr1[0] = 2
arr1[0][0] = 2
arr1.push(3)

console.log(arr1) // [2, [2, 2], 3]
console.log(arr2) // [1, [2, 2]]
console.log(arr3) // [1, [2, 2]]

Array 自带方法的拷贝属于浅拷贝

深拷贝

基础类型和引用类型单独管理

JSON

let obj1 = {
    a: 1,
    b: [1, 2],
    c: () => {}
}

let obj2 = JSON.parse(JSON.stringify(obj1))

obj1.a = 2
obj1.b[0] = 2

console.log(obj1) // { a: 2, b: [2, 2], c: () => {} }
console.log(obj2) // { a: 1, b: [1, 2] }

修改 obj1 ,obj2 基础类型和引用类型没有变化,但是 obj2.c 不见了。源自于 JSON.stringify() 数据处理导致

使用 JSON.parse() 需要包裹 try catch,毕竟这个出错会导致程序终止

递归

let obj1 = {
    a: 1,
    b: {
        b1: 1
    }
}

let obj2 = deepFun(obj1)

obj1.a = 2
obj1.b.b1 = 2

console.log(obj1) // { a: 2, b: { b1: 2 } }
console.log(obj2) // { a: 1, b: { b1: 1 } }

function deepFun(obj) {
    let objc = {}
    for (const key in obj) {
        if (typeof obj[key] === 'object') {
            objc[key] = deepFun(obj[key])
        } else {
            objc[key] = obj[key]
        }
    }
}

上面是对纯对象的一种递归深拷贝的实现,这里体现的主要是思路,实际情况需要考虑到其他变量类型

总结

  1. 浅拷贝和深拷贝区别在于是否有对引用类型数据进行处理

  2. 开发过程中两种拷贝都有存在的可能性,学习理解这两者的概念可以让我们从被拷贝困惑到成为拷贝的受益者