const clone = Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
);
不是深拷贝,循环引用、各种数据类型都可以拷贝,引用类型不是深拷贝
参考阮一峰文档: https://es6.ruanyifeng.com/#docs/object-methods#Object-assign
不是深拷贝,循环引用、各种数据类型都可以拷贝,引用类型不是深拷贝
Uncaught TypeError: Converting circular structure to JSON
// 待拷贝的对象
let originObj = {
re: /hello/,
ff: function () {},
sym: Symbol(123),
date: new Date(),
mp: new Map(),
st: new Set(),
a: "aaa",
b: 123,
c: true,
d: undefined,
e: null,
f: {
f1: "fff",
f2: { a: "aaa", b: 123, c: true, d: undefined, e: null },
f3: [{ a: "aaa", b: 123, c: true, d: undefined, e: null }, "f666", 666],
},
g: [1, 2, 3],
h: [{ a: "aaa", b: 123, c: true, d: undefined, e: null }, "f666", 666],
};
var obj222 = {
a: originObj,
};
originObj.obj222 = obj222;
// 简单实现,缺点:没有考虑 Date/RegExp/Set/Map/循环引用,如果有循环引用会报错栈溢出
function cloneDeep(obj) {
let objClone = obj.constructor === Array ? [] : Object.create({});
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
// Object.prototype.toString.call(/123/)
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = cloneDeep(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
return objClone;
}
// 详细实现
/**
* 深拷贝关注点:
* 1. JavaScript内置对象的复制: Set、Map、Date、RegExp等
* 2. 循环引用问题
* @param {*} object
* @returns
*/
function deepClone(source, memory) {
const isPrimitive = (value) => {
return /Number|Boolean|String|Null|Undefined|Symbol|Function/.test(
Object.prototype.toString.call(value)
);
};
let result = null;
let type = Object.prototype.toString.call(source);
memory || (memory = new WeakMap());
// 原始数据类型及函数
if (isPrimitive(source)) {
// console.log("current copy is primitive", source);
result = source;
}
// 数组
else if (Array.isArray(source)) {
result = source.map((value) => deepClone(value, memory));
}
// 内置对象Date、Regex
else if (type === "[object Date]") {
result = new Date(source);
} else if (type === "[object RegExp]") {
result = new RegExp(source);
}
// 内置对象Set、Map
else if (type === "[object Set]") {
result = new Set();
for (const value of source) {
result.add(deepClone(value, memory));
}
} else if (type === "[object Map]") {
result = new Map();
for (const [key, value] of source.entries()) {
result.set(key, deepClone(value, memory));
}
}
// 引用类型
else {
if (memory.has(source)) {
result = memory.get(source);
} else {
result = Object.create(null);
memory.set(source, result);
Object.keys(source).forEach((key) => {
const value = source[key];
result[key] = deepClone(value, memory);
});
}
}
return result;
}
console.log(cloneDeep(originObj));
console.log(deepClone(originObj));
参考:https://github.com/shfshanyue/Daily-Question/issues/203#issuecomment-888238489