参考链接https://juejin.cn/post/6844904002799288334

基本类型是不存在深拷贝和浅拷贝的,因为基本类型是不可变的,无论是修改、重新赋值、赋值给别的变量都是一个新的值,和原来的值再无关联。

引用类型因为是地址引用,所以会存在深拷贝和浅拷贝。

浅拷贝

创建一个复制对象B,这个对象B拥有着原始对象A属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是值,如果属性是引用类型,拷贝的就是内存地址。所以无论对象A还是对象B,如果修改了其中一个属性的引用类型的值,都会影响到另一个。

深拷贝

创建一个复制对象B,这个对象B把原始对象A的所有属性的拷贝一份,并且把属性是引用类型的引用地址和内存空间都会被拷贝一份,重新分配内存空间。修改新对象不会影响原始对象。

常见的浅拷贝

Object.assign()

语法: Object.assign(target, …sources); 返回值: target对象

Object.assign()是ES6中拷贝对象的一个方法,第一个参数target是拷贝的目标对象,第二个参数sources是传入对象,最终返回target对象。

  1. var target = { firstname: 'target', age: 10 };
  2. var source = { lastname: 'source', age: 20 };
  3. const newtarget = Object.assign(target, source);
  4. console.log(target);// { lastname: 'source', age: 20, firstname: 'target' }
  5. // target与newtarget指向同一个内存地址
  6. console.log(newtarget === target); // true

Array.prototype.slice()

slice() 方法返回一个新的数组对象,这个数组对象是原数组对象的一段浅拷贝。所以修改新数组对象的引用类型属性,原对象也会受到影响,它们的值指向同一个内存地址。

  1. var oldArr = [1, 2, [3, 4]];
  2. var newArr = oldArr.slice(0);
  3. oldArr[2][0] = 10
  4. console.log(newArr) // [1, 2, [10, 4]]

Array.prototype.concat()

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组,也是浅拷贝,同slice().

解构

解构是ES6中的新特性,它可以方便地浅拷贝一个对象。

  1. // 声明一个对象
  2. var old = {
  3. name: 'old',
  4. attr: {
  5. age: 18,
  6. sex: 'man'
  7. }
  8. };
  9. // 通过解构复制attr出来,它只复制了内存地址
  10. var { attr } = old;
  11. console.log(attr); // {age: 18, sex: "man"}
  12. // 修改原对象的attr值,新对象受到影响
  13. old.attr.age = 20;
  14. console.log(attr); // {age: 20, sex: "man"}

…扩展运算符

…扩展运算符也是 ES6 中的新特性,它也可以方便地浅拷贝一个对象。

  1. // 声明一个对象
  2. var old = {
  3. name: 'old',
  4. attr: {
  5. age: 18,
  6. sex: 'man'
  7. }
  8. };
  9. // 通过...扩展运算符,它只复制了内存地址
  10. var newValue = {...old};
  11. console.log(newValue); // {name: "old", attr: {age: 18, sex: "man"}}
  12. // 修改原对象的attr.age值,新对象受到影响
  13. old.attr.age = 20;
  14. console.log(newValue); // {name: "old", attr: {age: 20, sex: "man"}}