1:递归深拷贝
function deepClone1(obj) {
const target = {};
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
if (typeof obj[key] === "object") {
target[key] = deepClone1(obj[key]);
} else {
target[key] = obj[key];
}
}
}
return target;
}
2: JSON.parse JSON.stringify
缺点: 1:变量不能是方法 函数直接被忽略掉了 2:不能循环调用
function deepClone2(target) {
if (typeof target === "object" && target !== null) {
return JSON.parse(JSON.stringify(target));
} else {
return target;
}
}
3 递归处理数组
function deepClone3(target) {
if (typeof target === "object" && target !== null) {
let result = Array.isArray(target) ? [] : {};
if (Array.isArray(target)) {
target.forEach((item, index) => {
result[index] = deepClone4(item);
});
} else {
Object.keys(target).forEach((key) => {
result[key] = deepClone4(target[key]);
});
}
return result;
} else {
return target;
}
}
终极版本
function deepClone4(target) {
// map解决循环引用的问题
const map = new Map(); // 用map将已经访问过得对象存起来
const clone = (obj) => {
// 如果是已经访问过得对象,直接返回 避免循环引用导致栈溢出
if (map.has(obj)) {
return obj;
}
if (obj === null || typeof obj !== "object") return obj;
if (obj instanceof Boolean) return new Boolean(obj.valueOf());
if (obj instanceof `Number`) return new Number(obj.valueOf());
if (obj instanceof String) return new String(obj.valueOf());
if (obj instanceof RegExp) return new RegExp(obj.valueOf());
if (obj instanceof Date) return new Date(obj.valueOf());
let cpObj = obj instanceof Array ? [] : {};
map.set(obj, 1);
for (let key in obj) {
cpObj[key] = clone(obj[key]);
}
return cpObj;
};
return clone(target);
}
测试用例
const temp = {};
const obj = {
a: temp,
b: undefined,
c: new RegExp(/\w/),
d: () => {
console.log(123);
},
};
temp.b = obj;
const finall = deepClone4(obj);
console.log(finall.d === obj.d);
finall.d();
console.log(finall);