# 题目描述
请你完成一个函数 —— 实现对象参数的深拷贝并返回拷贝之后的新对象
要求:
- 需要考虑函数,正则,日期和
ES6新对象 - 需要考虑循环引用问题
 
# 分析
- 判断是否为对象是否为空,判断对象类型
 - 因为有函数,正则这些类型,所以要用正则来判断,如果是这些类型的对象,就直接返回一个新的该对象  —— 利用
target.constructor来访问到父类的构造函数 - 循环引用 —— 要使用map来存储<属性值,深拷贝对象>,如果该属性已经被深拷贝过了,就返回当前的深拷贝对象
 - 开始深拷贝 —— 递归
 
# 测试用例
function test() {
  const o1 = {
    name: "g",
    age: 18,
    o: { name: "o" },
    a: [1, 2],
    r: new RegExp(),
    d: new Date(),
  };
  o1.self = o1;
  const o2 = _completeDeepClone(o1);
  o1.name = "z";
  o1.age = 1;
  const judge =
    o1.name !== o2.name &&
    o1.age !== o2.age &&
    o1.o !== o2.o &&
    o1.a !== o2.a &&
    o1.r !== o2.r &&
    o1.d !== o2.d &&
    o1.self.self.self.self.self.self.self.self.self === o1.self &&
    o1.self !== o2.self;
  return judge;
}
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 代码实现
function test() {
  const o1 = {
    name: "g",
    age: 18,
    o: { name: "o" },
    a: [1, 2],
    r: new RegExp(),
    d: new Date(),
  };
  o1.self = o1;
  const o2 = _completeDeepClone(o1);
  o1.name = "z";
  o1.age = 1;
  const judge =
    o1.name !== o2.name &&
    o1.age !== o2.age &&
    o1.o !== o2.o &&
    o1.a !== o2.a &&
    o1.r !== o2.r &&
    o1.d !== o2.d &&
    o1.self.self.self.self.self.self.self.self.self === o1.self &&
    o1.self !== o2.self;
  return judge;
};
const _completeDeepClone = (target, map = new Map()) => {
  if (!target || typeof target != "object") {
    return target;
  }
  let reg = /^(RegExp|Funtion|Data|Map|Set)$/;
  // constructor指向构造函数
  const constructor = target.constructor;
  if (reg.test(constructor.name)) {
    return new constructor(target);
  }
  // 防止递归调用一个属性
  if (map.get(target)) {
    return map.get(target);
  }
  const cloneTarget = Array.isArray(target) ? [] : {};
  map.set(target, cloneTarget);
  Object.keys(target).forEach((prop) => {
    if (target.hasOwnProperty(prop)) {
      // 递归拷贝
      cloneTarget[prop] =
        typeof target[prop] === "object"
          ? _completeDeepClone(target[prop], map)
          : target[prop];
    }
  });
  return cloneTarget;
};
console.log(test());
// true
 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57