前言:

在阐述深拷贝与浅拷贝的问题时,我们需要对于Js的两大数据类型有所了解

基本类型:

  • Number
  • String
  • Boolean
  • Null
  • Undefined
  • Symbol

引用类型:

  • Array
  • Object
  • Function

基本类型数据保存在在栈内存中,引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中

打个比方来说基本类型就是外卖小哥直接把东西送到门卫放着你直接去拿就好了

但是对于引用类型来说,外卖小哥送来的东西是放在快递柜里的,你需要去快递柜里拿,

但是呢你又不知道是哪个快递柜,所以你就需要找外卖小哥留在门卫那里的快递柜号,

所以引用类型的数据在拷贝的时候就需要考虑这个快递柜号的问题,快递柜号所对应的就是引用地址

这里的门卫对应的就是栈内存,快递柜对应的就是堆内存

浅拷贝

浅拷贝就是拷贝一层,深层次的对象级别的则拷贝引用。

即浅拷贝只复制对象的第一层属性,而如果对象的属性值是引用类型的话,浅拷贝会复制其引用地址,因此如果修改其值,会影响到原对象。

浅拷贝的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
let person = {
name: '张三',
age: 18,
address: {
city: '北京',
area: '朝阳区'
}
}
let person1 = person;
person1.name = '李四';
person1.address.city = '上海';
console.log(person); // { name: '李四', age: 18, address: { city: '上海', area: '朝阳区' } }
console.log(person1); // { name: '李四', age: 18, address: { city: '上海', area: '朝阳区' } }

可以看到,当修改person1的name属性时,person的name属性也发生了变化,这是因为person和person1指向的是同一个对象,它们共享同一块内存空间。

当修改person1的address属性时,person的address属性也发生了变化,这是因为address属性是一个引用类型,浅拷贝只复制了address属性的引用地址,而没有复制address对象本身。因此,当修改address对象时,person的address属性也会发生变化。

深拷贝

深拷贝就是拷贝多层,拷贝对象及其子对象。深拷贝会拷贝所有的属性,并拷贝属性指向的内存,如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,因此如果修改其值,不会影响到原对象。

深拷贝的实现(此处只列举了两种):

  • 依次赋值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    const person = {
    name: '张三',
    age: 18,
    address: {
    city: '北京',
    area: '朝阳区'
    }
    };
    const person1 = {}
    person1.name = person.name;
    person1.age = person.age;
    person1.address = {};
    person1.address.city = person.address.city;
    person1.address.area = person.address.area;

    person1.name = '李四';

    console.log(person.name); //张三
    console.log(person1.name); //李四
  • lodash的cloneDeep方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    const _ = require('lodash');
    const person = {
    name: '张三',
    age: 18,
    address: {
    city: '北京',
    area: '朝阳区'
    }
    };
    const person1 = _.cloneDeep(person);

    person1.name = '李四';

    console.log(person.name); //张三
    console.log(person1.name); //李四

总结

浅拷贝只复制一层,对于引用类型,修改其中一个对象的属性值,另一个对象的属性值也会发生变化。

深拷贝会复制所有的属性,对于引用类型,修改其中一个对象的属性值,另一个对象的属性值不会发生变化。

至于上述都没有涉及到基本类型的拷贝,因为基本类型在拷贝的时候,会直接赋值,所以不存在浅拷贝和深拷贝的问题