简单版:
const newObj = JSON.parse(JSON.stringify(oldObj));
局限性:
他无法实现对函数 、RegExp等特殊对象的克隆
会抛弃对象的constructor,所有的构造函数会指向Object
对象有循环引用,会报错;
面试简版
function deepCopy(object) {
// 只拷贝对象
if (!object || typeof object !== "object") return;
// 根据 object 的类型判断是新建一个数组还是对象
let newObj = Array.isArray(object) ? [] : {};
// 遍历 object,并且判断是 object 的属性才拷贝
for (let key in object) {
if (object.hasOwnProperty(key)) {
newObj[key] = typeof object[key] === "object" ? deepCopy(object[key]) : object[key];
}
}
return newObj;
}
进阶版
解决拷贝循环引用问题
解决拷贝对应原型问题
function deepClone(target) {
const map = new WeekMap();
function isObject(target) {
return (typeof target === "object" && target) || (typeof target === "function");
}
function clone(data) {
if (!isObject(target)) {
return;
}
if ([Date, RegExp].includes(data.constructor)) {
return new data.constructor(data);
}
if (typeof data === "function") {
return new Function("return " + data.toString())();
}
const exist = map.get(data);
if (exist) {
return exist;
}
if (data instanceof Map) {
const result = new Map();
map.set(data, result);
data.forEach((val, key) => {
if (isObject(val)) {
result.set(key, clone(val));
} else {
result.set(key, val);
}
});
return result;
}
if (data instanceof Set) {
const result = new Set();
map.set(data, result);
data.forEach(val => {
if (isObject(val)) {
result.add(clone(val));
} else {
result.add(val);
}
});
return result;
}
const keys = Reflect.ownKeys(data);
const allDesc = Object.getOwnPropertyDescriptors(data);
const result = Object.create(Object.getPrototypeOf(data), allDesc);
map.set(data, result);
keys.forEach(key => {
const val = data[key];
if (isObject(val)) {
result[key] = clone(val);
} else {
result[key] = val;
}
});
return result;
}
return clone(target);
}