函数深拷贝写法

2/23/2023 programming

# 1. 请实现一个用javascript实现的深拷贝方法

查看答案
function deepCopy(obj) {
  // 判断是否为对象
  if (typeof obj !== "object" || obj === null) {
    return obj;
  }

  // 判断是否为数组
  if (Array.isArray(obj)) {
    return obj.map((item) => deepCopy(item));
  }

  // 处理对象
  const newObj = {};
  Object.keys(obj).forEach((key) => {
    newObj[key] = deepCopy(obj[key]);
  });
  return newObj;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 2. 递归的深拷贝方法容易造成栈溢出,有没有优化的写法?

这种情况可以通过添加一个缓存数组,用于存储已经处理过的对象引用,从而解决这个问题。这个方法可以避免重复处理已经处理过的对象,从而避免无限递归。

以下是一个优化后的深拷贝方法:

在这个方法中,添加了一个缓存数组cache,用于存储已经处理过的对象引用。在处理数组时,先检查缓存中是否已经存在相同的引用,如果存在则直接返回缓存中的引用,否则将处理结果加入缓存中。在处理对象时,也先检查缓存中是否已经存在相同的引用,如果存在则直接返回缓存中的引用,否则将处理结果加入缓存中,并遍历对象的每个属性进行递归处理。

这种方法可以有效避免栈溢出问题,同时也避免了重复处理已经处理过的对象。

查看答案
function deepCopy(obj, cache = []) {
  // 判断是否为对象
  if (typeof obj !== "object" || obj === null) {
    return obj;
  }

  // 判断是否为数组
  if (Array.isArray(obj)) {
    // 处理数组
    const result = obj.map((item) => deepCopy(item, cache));
    cache.push(obj, result);
    return result;
  }

  // 处理对象
  const cachedResult = findCache(cache, obj);
  if (cachedResult) {
    return cachedResult;
  }

  const result = {};
  cache.push(obj, result);
  Object.keys(obj).forEach((key) => {
    result[key] = deepCopy(obj[key], cache);
  });
  return result;
}

function findCache(cache, obj) {
  const cachedResult = cache.find((item) => item[0] === obj);
  return cachedResult && cachedResult[1];
}
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

# 3. 是否有key是Symbol的情况,这种情况用这个缓存还能行吗?

如果对象的属性名是Symbol类型,使用上述方法会存在问题,因为Symbol类型的属性名不会在Object.keys中被列出。为了解决这个问题,可以使用Object.getOwnPropertySymbols方法来获取对象的Symbol属性名。同时,在缓存中也需要使用Map对象来存储键值对,因为Map对象可以支持任意类型的键,包括Symbol类型。

以下是一个支持Symbol属性名的深拷贝方法:

在这个方法中,使用Map对象来存储缓存,使用get方法获取已经处理过的对象,使用set方法将处理结果加入缓存中。同时,在处理对象时,使用Object.getOwnPropertySymbols方法获取对象的Symbol属性名,并递归处理每个属性。

这种方法可以有效地处理对象的Symbol属性名,同时也避免了重复处理已经处理过的对象。

查看答案
function deepCopy(obj, cache = new Map()) {
  // 判断是否为对象
  if (typeof obj !== "object" || obj === null) {
    return obj;
  }

  // 判断是否为数组
  if (Array.isArray(obj)) {
    // 处理数组
    const result = obj.map((item) => deepCopy(item, cache));
    cache.set(obj, result);
    return result;
  }

  // 处理对象
  const cachedResult = cache.get(obj);
  if (cachedResult) {
    return cachedResult;
  }

  const result = {};
  cache.set(obj, result);
  Object.keys(obj).forEach((key) => {
    result[key] = deepCopy(obj[key], cache);
  });
  Object.getOwnPropertySymbols(obj).forEach((symbol) => {
    result[symbol] = deepCopy(obj[symbol], cache);
  });
  return result;
}
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
更新时间: 2023-02-24 11:36