// 递归
function dfsCloneDeep(source, hash = new WeakMap()) {
if (!typeof sorce === 'object') return source; // 非对象返回自身
if (hash.has(source)) return hash.get(source); // 查哈希表,如果以拷贝,则直接返回值,解决循环引用
let target = Array.isArray(source) ? [] : {}; // 区分数组和对象
hash.set(source, target); // 哈希表设值,哈希表存储已拷贝过的对象
let symKeys = Object.getOwnPropertySymbols(source); // 解决拷贝symbol
if (symKeys.length) {
symKeys.forEach(symKey => {
if (typeof source[symKey] === 'object' && source[symKey] !== null) {
target[symKey] = dfsCloneDeep(source[symKey], hash);
} else {
target[symKey] = source[symKey];
}
});
}
for(let key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
if (typeof source[key] === 'object' && source[key] !== null) {
target[key] = dfsCloneDeep(source[key], hash); // 注意这里传入hash
} else {
target[key] = source[key];
}
}
}
return target;
}
// 队列
function bfsCloneDeep(obj) {
let root = Array.isArray(obj) ? [] : {};
let nodeList = [{
parent: root,
key: undefined,
data: obj,
}];
while (nodeList.length) {
let node = nodeList.pop(),
parent = node.parent,
key = node.key,
data = node.data;
let result = parent;
if (typeof key !== 'undefined') { // 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素
result = parent[key] = Array.isArray(data) ? [] : {};
}
let symKeys = Object.getOwnPropertySymbols(data); // 解决拷贝symbol
if (symKeys.length) {
symKeys.forEach(symKey => {
if (typeof data[symKey] === 'object' && data[symKey] !== null) {
nodeList.push({
parent: result,
key: symKeys,
data: data[symKey],
});
} else {
result[symKey] = data[symKey];
}
});
}
for (let key in data) {
if (data.hasOwnProperty(key)) {
if (typeof data[key] === 'object') {
nodeList.push({
parent: result,
key,
data: data[key],
});
} else {
result[key] = data[key];
}
}
}
}
return root;
};
let obj = {colors: ['blue', 'red'],width: 200, height: 300};
let l = Symbol('length');
obj[l] = 400 ;
let obj1 = bfsCloneDeep(obj)
// {colors: ['blue', 'red'], width: 200, height: 300, Symbol(length): 400}
let obj2 = dfsCloneDeep(obj)
// {colors: ['blue', 'red'], width: 200, height: 300, Symbol(length): 400}