js实现深拷贝(deepClone)
2023-12-14 本文已影响0人
技术体验师_萦回
首先我们要实现一个getType函数对元素进行类型判断,直接调用Object.prototype.toString 方法。
function getType(obj) {
let map = {
"[object Boolean]": "boolean",
"[object Number]": "number",
"[object String]": "string",
"[object Function]": "function",
"[object Array]": "array",
"[object Date]": "date",
"[object RegExp]": "regExp",
"[object Undefined]": "undefined",
"[object Null]": "null",
"[object Object]": "object",
};
if (obj instanceof Element) {
return "element";
}
return map[Object.prototype.toString.call(obj)];
}
继续
deepClone递归实现
function deepClone(target) {
const type = getType(target);
if (type == "array" || type == "object") {
let _clone;
// 复杂数据类型 递归实现
if (type == "array") {
_clone = [];
target.forEach((element) => {
_clone.push(deepClone(element));
});
} else {
_clone = {};
for (const key in target) {
if (Object.hasOwnProperty.call(target, key)) {
const element = target[key];
_clone[key] = deepClone(element);
}
}
}
return _clone;
} else {
// 基础数据类型 直接返回
return target;
}
}
对于function类型,这里是直接赋值的,还是共享一个内存值。这是因为函数更多的是完成某些功能,有个输入值和返回值,而且对于上层业务而言更多的是完成业务功能,并不需要真正将函数深拷贝。
处理循环引用
function deepClone(target,stack) {
const type = getType(target);
if (type == "array" || type == "object") {
let _clone;
if(type == "array") _clone = [];
if(type == "object") _clone = {};
// 检查循环引用并返回其对应的克隆
stack || (stack = new WeakMap());
var stacked = stack.get(target);
if (stacked) {
return stacked;
}
stack.set(target, _clone);
// 复杂数据类型 递归实现
if (type == "array") {
target.forEach((element) => {
_clone.push(deepClone(element, stack));
});
} else {
for (const key in target) {
if (Object.hasOwnProperty.call(target, key)) {
const element = target[key];
_clone[key] = deepClone(element, stack);
}
}
}
return _clone;
} else {
// 基础数据类型 直接返回
return target;
}
}
测试用例如下
// 测试用例3 循环引用
var objA = {
name:'a'
};
var objB = {
name:'b'
};
objA.prop = objB;
objB.prop = objA;
console.log(deepClone(objA))