Contents

浅拷贝与深拷贝

在了解深浅拷贝前需要首先先谈谈拷贝的概念

拷贝

拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,

浅拷贝

浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址。

深拷贝

深拷贝,在拷贝引用类型成员变量时,为引用类型的数据成员另辟了一个独立的内存空间,实现真正内容上的拷贝。

浅拷贝的四种方式

1.键值拷贝

let pl={name:'plumli'};
let plum={name:pl.name};
console.log(plum); // {"name":"plumli"}
plum.name='plum';
console.log(pl); // {"name":"plumli"}
console.log(plum); // {"name":"plum"}

2.for循环拷贝

let pl = { name: 'lyh', url: 'plumli.xyz' };
let obj = {};
for (const key in pl) {
  obj[key] = pl[key]
}
obj.name = 'plumli'; 
console.log(obj); // {"name":"plumli","url":"plumli.xyz"}
console.log(pl); // {"name":"lyh","url":"plumli.xyz"}

3.assign方法拷贝

let pl = { name: 'lyh', url: 'plumli.xyz' };
let obj = Object.assign({}, pl)
obj.name = 'plumli';
console.log(pl); // {"name":"lyh","url":"plumli.xyz"}
console.log(obj); // {"name":"plumli","url":"plumli.xyz"}

4.解构方法拷贝


let pl = { name: 'lyh', url: 'plumli.xyz' };
let obj = { ...pl };
console.log(obj); // {"name":"lyh","url":"plumli.xyz"}

深拷贝方法

当拷贝的对象里面又有新的对象时,此时进行普通方法的拷贝只是拷贝到了新的对象的内存地址,当拷贝的对象内的对象值发生变化时,新拷贝的对象值也会发生变化。此时就需要进行深拷贝。

深拷贝中对象和数组类型本质上都是对象数据类型,如果经过普通深拷贝后对象里数组的数组方法可能不可用,下边先来介绍一下简单版的深拷贝。

简单版

let obj1 = {
  name: 'obj1name',
  age: 18,
  hobbies: {
    one: 'eat',
    two: 'sleep'
  }
}
function copy(object) {
  let res = {};
  for (const key in object) {
    res[key] = typeof object[key] === 'object' ? copy(object[key]) : object[key]
  }
  return res
}
let obj2 = copy(obj1);
obj2.hobbies.three = 'play'; // 如果 改变obj2内对象的值,obj1内对象的值不变,即为拷贝成功
console.log('obj1', JSON.stringify(obj1, null, 2));
// obj1 {
//   "name": "obj1name",
//   "age": 18,
//   "hobbies": {
//     "one": "eat",
//     "two": "sleep"
//   }
console.log('obj2', JSON.stringify(obj2, null, 2));
// obj2 {
//   "name": "obj1name",
//   "age": 18,
//   "hobbies": {
//     "one": "eat",
//     "two": "sleep",
//     "three": "play"
//   }
// }

简单般的深拷贝方法无法拷贝数组对象,现在来看升级版

升级版

介绍:Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。

let obj1 = {
  name: 'obj1name',
  age: 18,
  hobbies: {
    one: 'eat',
    two: 'sleep'
  },
  lessons: ['javascript', 'css']
}
function copy(object) {
  let res = object instanceof Array ? [] : {};
  for (const [k, v] of Object.entries(object)) {
    res[k] = typeof v === 'object' ? copy(v) : v
  }
  return res
}
let obj2 = copy(obj1);
obj2.hobbies.three = 'play';
obj2.lessons.push('html');
console.log('obj1', JSON.stringify(obj1, null, 2));
// obj1 {
//   "name": "obj1name",
//   "age": 18,
//   "hobbies": {
//     "one": "eat",
//     "two": "sleep"
//   },
//   "lessons": [
//     "javascript",
//     "css"
//   ]
// }
console.log('obj2', JSON.stringify(obj2, null, 2));
// obj2 {
//   "name": "obj1name",
//   "age": 18,
//   "hobbies": {
//     "one": "eat",
//     "two": "sleep",
//     "three": "play"
//   },
//   "lessons": [
//     "javascript",
//     "css",
//     "html"
//   ]
// }

以上为本阶段学习拷贝的一点理解,以后若接触到更多会逐步添加…