使用MessageChannel实现深度克隆
兼容浏览器环境和Node.js环境
js
function deepClone(obj) {
return new Promise((resolve) => {
const { port1, port2 } = new MessageChannel()
port1.postMessage(obj)
port2.onmessage = (message) => {
resolve(message.data)
// 如果不加这两行代码,在Node环境中会一直挂起,不会结束
port1.close()
port2.close()
}
})
}有循环引用的对象也能原封克隆
深度克隆的通用方法
支持Object、Array、Date、RegExp、DOM
js
function deepClone(sourceObj) {
if (typeof sourceObj !== 'object')
return;
let newObj = sourceObj instanceof Array ? [] : {};
for (let key in sourceObj) {
if (sourceObj.hasOwnProperty(key)) {
if (!(key in newObj)) {
if (sourceObj[key] instanceof Date) {
newObj[key] = new Date(sourceObj[key].getTime());
}
else if (sourceObj[key] instanceof RegExp) {
newObj[key] = new RegExp(sourceObj[key]);
}
else if (typeof sourceObj[key] === 'object' &&
sourceObj[key].nodeType === 1) {
let domEle = document.getElementsByTagName(sourceObj[key].nodeName)[0];
newObj[key] = domEle.cloneNode(true);
}
else {
newObj[key] =
typeof sourceObj[key] === 'object'
? deepClone(sourceObj[key])
: sourceObj[key];
}
}
}
}
return newObj;
}深度克隆的其他方法
lodash-es的cloneDeep、cloneDeepWith