一步学会手动实现深浅拷贝

295 阅读2分钟

1.赋值

赋值是将某一数值或对象赋给某个变量的过程

  • 基本数据类型:赋值,赋值之后两个变量互不影响
  • 引用数据类型:赋址,两个变量具有相同的引用,指向同一个对象,相互之间有影响

通常在开发中并不希望改变变量 a 之后会影响到变量 b,这时就需要用到浅拷贝和深拷贝。

2.浅拷贝,深拷贝区别

深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。

浅拷贝:只拷贝一层,更深层对象级别的只是拷贝引用。 (是同一个内存地址) 深拷贝:拷贝多层,每一个级别的数据都会拷贝。

区别:深拷贝和浅拷贝最根本的区别在于。浅拷贝与原数据指向的是同一个内存地址,深拷贝

如何区分:对于复杂一点的对象B复制了A,修改A时看B是否发生变化:B变化了是浅拷贝,B没有变化是深拷贝

3.浅拷贝实现

简单来说可以理解为浅拷贝只解决了第一层的问题,拷贝第一层的基本类型值,以及第一层的引用类型地址。

实现方法:1. 利用for in

2.利用Object.assgin();

3.Array.concat()或 a.slice() 只针对数组

let o = {
  id: 1,
  name: 'cao',
  msg: { age: 18 }
  }
let obj = {};
for (var k in o) {
 obj[k] = o[k]
}
 o.msg.age = 20;
 o.name = "cao1"
 console.log(obj);
 console.log(o);
 或者:Object.assign(obj, o); 
 
详解:浅拷贝只拷贝了一层,因此name作为第一层的基数据,没有影响
      msg作为引用数据,只拷贝了引用地址,因此有影响

let a = [1, 2, 3, 4],
b = a.slice();
a[0] = 2;
console.log(a, b);

4.深拷贝实现

深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。

当对象和它所引用的对象一起拷贝时即发生深拷贝。

深拷贝相比于浅拷贝速度较慢并且花销较大。

拷贝前后两个对象互不影响。

实现方法:1. 利用for in + 递归

2.利用Json.parse(Json.stringfy(object));

1.方法1
  let o = {
   name: 'cao',
   msg: { age: 18 }
   }
 let obj = {};
 obj = JSON.parse(JSON.stringify(o))
 o.msg.age = 20;
 o.name = "cao1";
 console.log(obj);
 console.log(o);

2.方法2
let o = {
 id: 1,
 name: 'cao',
 msg: { age: 18, other: { color: "red" } },
 num: [1, 3, 4]
 }
let obj = {};

function deep(oldObj, newObj) {
 for (var k in oldObj) {
  var item = oldObj[k];
  if (item instanceof Array) {//判断是否为数组
   newObj[k] = [];
   newObj[k] = deep(item, newObj[k]);
   } else if (item instanceof Object) {//判断是否为对象
    newObj[k] = {};
    newObj[k] = deep(item, newObj[k])
    } else {//基本数据类型
       newObj[k] = item;
       }
  }
 return newObj
}
 deep(o, obj)
 o.msg.age = 20;
 o.name = "cao1";

 console.log(obj);
 console.log(o);

注意:方法1:JSON.parse(JSON.stringify(object))缺陷:
     会忽略 undefined
     会忽略 symbol
     不能序列化函数
     不能解决循环引用的对象