浅拷贝与深拷贝

131 阅读2分钟

(zhuanlan.zhihu.com/p/56741046)

一、数据类型

  1. 基本数据类型:String、Number、Boolean、undefined、null、Symbol
  2. 引用数据类型:Object、Array、Function

二、浅拷贝与深拷贝

1. 什么时候需要拷贝?

在实际开发过程中,有时候我们需要使用某个变量的值,如果这个变量是基本数据类型,那直接赋值即可;如果它的值是一个对象,这个时候直接赋值是不行的,因为对象在 JavaScript 中是引用数据类型,变量中存储的是该对象在内存中的地址引用,赋值操作只是将该内存地址重新赋值给一个新的变量,这个时候两个变量实际上指向的是同一个对象。

// 定义一个对象
const info = {
  name: "caohan",
  age: "27",
  friend: {
    name: "ch"
  }
};
const obj = info; // 此时 info 跟 obj 指向的是同一个对象
info.name = 'tangting'
console.log(obj.name); // tangting

这个时候我们就需要使用拷贝,将原有的对象拷贝一份。

2. 浅拷贝

创建一个新的对象,来保存所需对象的所有属性值。浅拷贝有如下实现方式:

1)Object.assign

// 定义一个对象
const info = {
  name: "caohan",
  age: "27",
  friend: {
    name: "ch"
  }
};
const obj = Object.assign({}, info); // 实现了浅拷贝
info.name = "tangting";
console.log(info.name); // tangting
console.log(obj.name); // caohan

2)扩展运算符

// 定义一个对象
const info = {
  name: "caohan",
  age: "27",
  friend: {
    name: "ch"
  }
};
const obj = { ...info }; // 实现了浅拷贝
info.name = "tangting";
console.log(info.name); // tangting
console.log(obj.name); // caohan

以上方法只实现了浅层的拷贝,如果对象中的属性的属性值也为引用数据类型,例如对象时,该方法就会存在问题,即:

// 如果修改 info 里面的 friend 里面的 name
// obj 里面的 friend 里面的 name 也会改变
info.friend.name = "tt";
console.log(info.friend.name); // tt
console.log(obj.friend.name); // tt

想要实现深层的拷贝,就要使用下面的方法。

3. 深拷贝

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

const info = {
  name: "caohan",
  age: "27",
  friend: { // 属性值为对象
    name: "ch"
  }
};
const obj = JSON.stringify(JSON.parse(info));
info.friend.name = "tt";
console.log(info.friend.name); // tt
console.log(obj.friend.name); // caohan

这种方法可以处理属性值为对象情况,如果是数组或函数就不可以了。

2)手写递归方法

递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝

3)函数库lodash

该函数库也有提供_.cloneDeep用来做 Deep Copy