深浅拷贝

浅拷贝

浅拷贝是指,一个新的对象对原始对象的属性值进行精确地拷贝,如果拷贝的是基本数据类型,拷贝的就是基本数据类型的值;如果拷贝的是引用数据类型,拷贝的就是内存地址。如果其中一个对象的引用内存地址发生改变,另一个对象也会发生变化。

浅拷贝方法

  1. Object.assign
  2. 扩展运算符
  3. 数组操作(slice、concat)

实现

1
2
3
4
5
6
7
8
9
10
function clone(params) {
if (!params || typeof params !== 'object') return params;

const o = Array.isArray(params) ? [] : {}

for(let key in params) {
o[key] = params[key]
}
return o;
}

深拷贝

深拷贝是指,对于简单数据类型直接拷贝他的值,对于引用数据类型,在堆内存中开辟一块内存用于存放复制的对象,并把原有的对象类型数据拷贝过来,这两个对象相互独立,属于两个不同的内存地址,修改其中一个,另一个不会发生改变

JSON序列化的问题

  1. 拷贝的对象中如果有函数,undefined,symbol,当使用过JSON.stringify()进行处理之后,都会消失。
  2. 无法拷贝不可枚举的属性;
  3. 无法拷贝对象的原型链;
  4. 拷贝 Date 引用类型会变成字符串;
  5. 拷贝 RegExp 引用类型会变成空对象;
  6. 对象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的结果会变成 null;
  7. 无法拷贝对象的循环应用,即对象成环 (obj[key] = obj)。

简单实现递归的深浅拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function deepClone(obj = {}, hash = new WeakMap()) {
if (obj instanceof Date) {
return new Date(obj)
}

if (obj instanceof RegExp) {
return new RegExp(obj)
}
if (hash.has(obj)) {
return hash.get(obj)
}
const alldec = obj.getOwnPropertyDescriptors(obj)

const newObj = Object.create(obj, alldec);

hash.set(obj, newObj);
for(const key of Object.keys(obj)) {
if (obj[key] !== null && typeof obj[key] === 'object') {
newObj[key] = deepClone(obj[key], hash)
} else {
newObj[key] = obj[key]
}
}
return newObj
}