JavaScript深拷贝
JavaScript深拷贝
function deepCloneDFS(origin, map = new Map()) {
// 循环引用检测
if (map.get(origin)) {
return origin;
}
// 把对象作为键名
map.set(origin, true)
// 命中策略
let constructorType = Object.prototype.toString.call(origin);
let fn = strategy[constructorType];
if (fn) {
return fn(origin, map);
}
// 没有命中策略的,使用自身的构造函数重建一个
const constructor = origin.constructor;
return new constructor(origin);
}
// 策略
var strategy = {
'[object Number]': function (origin) { return origin },
'[object String]': function (origin) { return origin },
'[object Boolean]': function (origin) { return origin },
'[object Null]': function (origin) { return origin },
'[object Undefined]': function (origin) { return origin },
'[object Symbol]': function (origin) {
return new Object(Symbol.prototype.valueOf.call(origin));
},
'[object BigInt]': function (origin) { return origin },
'[object Function]': function (origin) {
// 箭头函数直接返回
if (!origin.prototype) {
return new Function(origin.toString());
}
// 普通函数需要正则处理处理
const bodyReg = /(?<={)(.|\n)+(?=})/m;
const paramReg = /(?<=\().+(?=\)\s+{)/;
const funcString = origin.toString();
// 分别匹配 函数参数 和 函数体
const param = paramReg.exec(funcString);
const body = bodyReg.exec(funcString);
if(!body) return null;
if (param) {
const paramArr = param[0].split(',');
return new Function(...paramArr, body[0]);
} else {
return new Function(body[0]);
}
},
// Map 得小心它的 key 和 value 都可能是个对象需要深拷贝
'[object Map]': function (origin, map) {
let result = new Map();
origin.forEach((item, key) => {
result.set(deepCloneDFS(key, map), deepCloneDFS(item, map));
})
return result;
},
'[object Set]': function (origin, map) {
let result = new Set();
origin.forEach((item) => {
result.add(deepCloneDFS(item, map));
});
return result;
},
'[object Array]': function(origin, map) {
let result = [];
origin.forEach((item, index) => {
result[index] = deepCloneDFS(item, map);
});
return result;
},
'[object Object]': function(origin, map) {
let result = {};
Object.keys(origin).forEach(key => {
result[key] = deepCloneDFS(origin[key], map);
});
return result;
}
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!