JavaScript中实现深拷贝的几个方法

序列化与反序列化

代码如下:

1
const b = JSON.parse ( JSON.stringify (a ) );

优点:简单

缺点:

  1. JSON 只有六种数据格式,所以在转化时不支持 Date、正则、undefined、函数等数据
  2. . 不支持引用(即环状结构)

递归实现

代码如下:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const deepClone = (a, cache) => {
if (!cache) {
cache = new Map();
// 缓存不能全局,最好临时创建并递归传递
}
if (a instanceof Object) {
// 不考虑跨iframe
if (cache.get(a)) {
return cache.get(a);
}
let result;
if (a instanceof Function) {
if (a.prototype) {
// 有 prototype 就是普通函数
result = function () {
return a.apply(this, arguments);
};
} else {
// 没有 prototype 就是箭头函数
result = (...args) => {
return a.call(undefined, ...args);
};
}
} else if (a instanceof Array) {
result = [];
} else if (a instanceof Date) {
result = new Date(a - 0); //a-0是为了转换成数字,变成时间戳
} else if (a instanceof RegExp) {
result = new RegExp(a.source, a.flags); // 正则
} else {
result = {};
}
cache.set(a, result);
for (let key in a) {
if (a.hasOwnProperty(key)) {
result[key] = deepClone(a[key], cache);
}
}
return result;
} else {
return a;
}
};

要点如下:

  • 递归的使用
  • 判断类型
  • 检查环(使用 Map 实现)
  • 不拷贝原型上的属性(使用 hasOwnProperty方法来实现)