函数深拷贝写法
狐七 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
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
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
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