Bootstrap

深拷贝与浅拷贝的区别(详细)手写实现深拷贝的函数/方法

深拷贝与浅拷贝首先本质上都是赋值一个对象,将a赋给b。

一、从内存来看(本质)

在创建一个对象时,会在内存中开辟一块空间,内存中存储变量的值 ,而变量名则是指向该空间的地址。

深拷贝是重新开辟一片内存空间,与原先的复制对象值相同,但地址不同,上图为深拷贝情况

如果是浅拷贝,指向的还是同一片内存空间,值相同,地址也相同

二、从赋值对象看

将a赋给b

深拷贝:不管a是什么,number,string,object 还是 array,拷贝出来的b为新对象,会拷贝a的每一层(a中可能有数组,对象的嵌套的情况)

浅拷贝:只拷贝第一层,如果第一层为对象,对象中有一个city也为对象(此时city为第二层),则city不会被拷贝。

如果文字描述难以理解,请看第四点中的例子,可以更好地理解。

三、实现深拷贝的方法 

1.最常用的方法,JSON转换

实现也很简单,一句话。可以应用于绝大多数情况

const deepClone1 = (value: any) => {
  return JSON.parse(JSON.stringify(value))
}

2.structuredClone(value)方法

const deepClone2 = (value: any) => {
  return structuredClone(value)
}

系统提供的一种深拷贝方法,但对Node及浏览器有版本要求,可适用性不高

要求Node:verison≥17.0.0

放一下该文档说明的链接,请自行查看   structuredClone() - Web API 接口参考 | MDN

3.手写实现

const deepClone3 = (value: any) => {
  if (typeof value != 'object' || value == null) {
    return value
  }

  let res = Array.isArray(value) ? [] : {}

  for (let el in value) {
    if (value.hasOwnProperty(el)) {
      res[el] = deepClone3(value[el])
    }
  }

  return res;
}

四、三种深拷贝方法的区别

请看下面的例子:

 我们在作拷贝的操作后(obj2 = obj) ,将obj2的值改动,观察obj2与obj值的变动情况。

用例1: string类型

 obj = '改变之前',

obj2=obj,

obj2='改变之后' 

可以发现,在把obj2的值改变后,此时无论是深拷贝(3种方法都一样)还是浅拷贝,obj的值还是一样。(因为string只有第一层,此时看不出差别)

用例2:对象类型

 //obj
{
    name: null,
    englishName: 'english',
    id: 111,
    cate: undefined,
    detail: {
      city: '中国',
      custom: ['客户1', '客户2'],
      info: {
        date: new Date(1998, 1, 1),
        price: 20000

      }
    }
  }


//分别深浅拷贝后,obj2的值作改变

{
    name: '新名字',
    englishName: 'english',
    id: 112,
    cate: undefined,
    detail: {
      city: '中国',
      custom: ['新客户', '客户2'],
      info: {
        date: new Date(1998, 1, 1),
        price: 20000

      }
    }
  }

先使用深拷贝方法1(JSON转换),接下来我们看结果:

可以发现:

1.无论是深还是浅拷贝,对象中的cate属性消失了,因为它是undefined(用console.log打印cate消失)

2.浅拷贝原来的obj也受到了影响

3.深拷贝中,obj没有受到影响

接下来试一下深拷贝方法2(原生API)

 结果与方法1一致

唯一区别:console.log打印cate存在

最后试一下深拷贝方法3(手写)

 与方法2一致,cate依旧存在

下图分别为深拷贝方法123所打印的结果:

得出结论:

1.浅拷贝仅可以拷贝第一层的数据,深拷贝是新生成一个相同的独立的对象,可以拷贝所有层的数据,之后再做的任何改动,都与原先的对象无关。

2.深拷贝方法中,使用JSON转换的方法可以适用大部分情况,但会深拷贝会丢失undefined数据

3.深拷贝方法中,系统方法对Node及浏览器版本要求较高

;