主题
对象深拷贝
如果对象可以序列化,可以使用 JSON.stringify() 将对象转换为 JSON 字符串,然后使用 JSON.parse() 将字符串转换回(新的)对象。
js
const newObj = JSON.parse(JSON.stringify(obj));许多 JavaScript 对象无法序列化,例如函数、符号、集合、Element 对象等,这个时候只能根据对应的类型重新创建数据。下面的 deepClone 方法实现了几种数据类型的深拷贝:
js
function deepClone(value) {
// 如果是基本数据类型,直接返回值(这里不对 symbol 和 function 做深拷贝,所以不排除)
if (typeof value !== 'object' || value === null) {
return value;
}
// 获取对象类型
const [, type] = /^\[object ([a-zA-Z]+)\]$/.exec(
Object.prototype.toString.call(value)
);
// Date、RegExp
if (type === 'Date' || type === 'RegExp') {
return new value.constructor(value);
}
const result = new value.constructor();
// Set
if (type === 'Set') {
for (const item of value) {
result.add(deepClone(item));
}
}
// Map
else if (type === 'Map') {
for (const [key, item] of value) {
result.set(deepClone(key), deepClone(item));
}
}
// Array、Object
else {
for (const key in value) {
if (value.hasOwnProperty(key)) {
result[key] = deepClone(value[key]);
}
}
}
return result;
}你可以根据实际需求增加对应的数据类型,比如:函数、符号、类型化数组等。另外,如果要深拷贝循环引用的对象,可以利用 WeakMap 缓存处理过的对象:
js
function deepClone(value) {
...
// 如果缓存里有这个对象直接返回结果
if (deepClone.cached.has(value)) {
return deepClone.cached.get(value);
}
...
deepClone.cached.set(value, result);
...
}
deepClone.cached = new WeakMap();