前端

JavaScript 深拷贝和浅拷贝

2022-03-24  本文已影响0人  暴躁程序员

拷贝的意思就是复制数据,打个比方,原有一个变量 a 的值是引用类型数据,要求新创建的变量 b 的值与 a 的值相同,
方案一(浅拷贝):让 b 直接共享a 的数据,那么 a 和 b 任何一方修改数据,另一方的数据也会同步变化
方案二(深拷贝):让 b 创建一个新的空间用来存储和 a 一样的数据,即 将 a 的数据,以递归的方式拷贝到 b 新创建的数据空间中

注意:

  1. 基础数据类型的值存储于栈中,他不涉及深浅拷贝(全是深拷贝)
  2. 引用类型的地址存储于栈中,指针指向存储于堆中的值,且其他变量的指针可通过赋值的方式指向同一个堆中的值,当堆中的值发生改变时,会造成所有变量的值同步变化

总结:浅拷贝 --- 拷贝引用类型的地址,深拷贝 --- 拷贝引用类型的值

浅拷贝

  1. 变量赋值的方式实现 数组和对象 的浅拷贝
// 数组浅拷贝
let a = [1, 2, 3, 4, 5];
let b = a;
b[0] = 1000; // 改变 b 的时候,同时也会改变 a
console.log(a); // [ 1000, 2, 3, 4, 5 ]

// 对象浅拷贝
let c = { name: 1, age: 1 };
let d = c;
d.name = 1000; // 改变 d 的时候,同时也会改变 c
console.log(c); // { name: 1000, age: 1 }
  1. Object.assign() 实现 对象 浅拷贝
// 对象浅拷贝
let a = { name: 1, age: 1 };
let b = Object.assign(a, { other: 999 });
b.name = 1000; // 改变 b 的时候,同时也会改变 a
console.log(a); // { name: 1000, age: 1, other: 999 }

// 注意:Object.assign的用法,a 写在第一位才是浅拷贝,写成Object.assign({ other: 999 }, a) ,是深拷贝
let c = Object.assign({ other: 999 }, a);
c.name = 888; // 改变 c 的时候,a 不会变化
console.log(a); // { name: 1000, age: 1, other: 999 }

深拷贝

  1. 递归的方式实现 数组和对象 的深拷贝
// 数组深拷贝
let a = [1, 2, 3, 4, 5];
let b = [];
for (let i = 0; i < a.length; i++) {
  b.push(a[i]);
}
b[0] = 1000; // 改变 b 的时候,a 不受影响
console.log(b); // [ 1000, 2, 3, 4, 5 ]
console.log(a); // [ 1, 2, 3, 4, 5 ]

// 对象深拷贝
let c = { name: 1, age: 1 };
let d = {};
for (const k in c) {
  if (Object.hasOwnProperty.call(c, k)) {
    d[k] = c[k];
  }
}
d.name = 1000; // 改变 d 的时候,c 不受影响
console.log(c); // { name: 1, age: 1 }
console.log(d); // { name: 1000, age: 1 }
  1. ... 拓展运算符的方式实现 数组和对象 的深拷贝
// 数组深拷贝
let a = [1, 2, 3, 4, 5];
let b = [...a];
b[0] = 1000; // 改变 b 的时候,a 的值不变
console.log(a); // [1, 2, 3, 4, 5];
console.log(b); // [ 1000, 2, 3, 4, 5 ]

// 对象深拷贝
let c = { name: 1, age: 1 };
let d = { ...c };
d.name = 1000; // 改变 d 的时候,c 的值不会变
console.log(c); // { name: 1, age: 1 }
console.log(d); // { name: 1000, age: 1
  1. 数组的 sliceconcat方法实现 数组 的深拷贝
// slice 实现 数组深拷贝
let a = [1, 2, 3, 4, 5];
let b = a.slice();
b[0] = 1000; // 改变 b 的时候,a 的值不变
console.log(a); // [1, 2, 3, 4, 5];
console.log(b); // [ 1000, 2, 3, 4, 5 ]

// concat 实现 数组深拷贝
let c = [1, 2, 3, 4, 5];
let d = a.concat();
d[0] = 1000; // 改变 b 的时候,a 的值不变
console.log(c); // [1, 2, 3, 4, 5];
console.log(d); // [ 1000, 2, 3, 4, 5 ]
上一篇下一篇

猜你喜欢

热点阅读