- WeakMap常規(guī)遍歷遞歸
function deepClone(source, map = new WeakMap()) { // 傳入一個(gè)WeakMap對(duì)象用于記錄拷貝前和拷貝后的映射關(guān)系
if (typeof source !== "object") { // 非對(duì)象類型(undefined、boolean嗤军、number、string、symbol),直接返回原值即可
return source;
}
if (source === null) { // 為null類型的時(shí)候
return source;
}
if (source instanceof Date) { // Date類型
return new Date(source);
}
if (source instanceof RegExp) { // RegExp正則類型
return new RegExp(source);
}
if (map.get(source)) { // 如果存在相互引用沐扳,則從map中取出之前拷貝的結(jié)果對(duì)象并返回以便形成相互引用關(guān)系
return map.get(source);
}
let result;
if (Array.isArray(source)) { // 數(shù)組
result = [];
map.set(source, result); // 數(shù)組也會(huì)存在相互引用
source.forEach((item) => {
result.push(deepClone(item, map)); // 必須傳入第一次調(diào)用deepClone時(shí)候創(chuàng)建的map對(duì)象
});
return result;
} else { // 為對(duì)象的時(shí)候
result = {};
map.set(source, result); // 保存已拷貝的對(duì)象
const keys = [...Object.getOwnPropertyNames(source), ...Object.getOwnPropertySymbols(source)]; // 取出對(duì)象的key以及symbol類型的key
keys.forEach(key => {
result[key] = deepClone(source[key], map); // 必須傳入第一次調(diào)用deepClone時(shí)候創(chuàng)建的map對(duì)象
});
return result;
}
}
- js原生api
structuredClone
structuredClone() - Web API 接口參考 | MDN (mozilla.org)
// structuredClone()
const m = {
a: 1,
date: new Date(),
// e: function foo (i) { i*10 },
// error: new Error('error message')
c: undefined,
d: null,
reg: /^1[3-9]\d{10}$/
}
const n = {
p: m
}
m.b = n
const r = structuredClone(m)
console.log(r)
限制
- 不允許克隆
Error
、Function
和DOM
對(duì)象葛圃,如果對(duì)象中含有默垄,將拋出DATA_CLONE_ERR
異常此虑。 - 不保留
RegExp
對(duì)象的lastIndex
字段。 - 不保留屬性描述符口锭,
setters
以及getters
(以及其他類似元數(shù)據(jù)的功能)朦前。例如,如果一個(gè)對(duì)象用屬性描述符標(biāo)記為read-only
鹃操,它將會(huì)被復(fù)制為read-write
韭寸。 - 不保留原形鏈
參數(shù)transfer Transferable objects
transferable object