废话不多说,直接代码伺候:
function deepClone(obj){
// 先判断不是引用数据类型的
if(typeof obj !== 'object' || !obj)return obj;
// 接下来判断引用数据类型
// Object.prototype.toString.call()判断更准确具体
let type = Object.prototype.toString.call(obj)
let typeObject = '[object Object]'
// 数组
if(typeof obj === 'object' && obj instanceof Array){
// 创建一个实例用来存储数据
// let result = new Array()
let result = new obj.constructor()
for (let key in obj) {
result[key] = deepClone(obj[key]);
}
return result
// 对象
}else if(type === typeObject){
// let result = new Object()
let result = new obj.constructor()
for (let key in obj) {
result[key] = deepClone(obj[key]);
}
return result
}
// 其他类型判断 ......
}
// 测试代码
const obj = {
name: "jack",
arr: [1, 2, 3],
arrObj: [{ n: 1 }, { m: 2 }],
fn: function () {},
nul: null,
undef: undefined,
};
let newObj = deepClone(obj)
console.log(newObj)
进阶版且解决环形对象
const obj = {
name: "jack",
age: 18,
bool: true,
f: function () {},
und: undefined,
nul: null,
hobby: { sport: "篮球" },
map: new Map(),
set: new Set(),
date: new Date(),
zz: /a/,
};
// 遇到环形时则会无限递归,导致栈内存溢出
const obj2 = { to: obj };
obj.to = obj2;
// 使用 WeakMap 解决强引用,处理环形对象带来的递归栈内存溢出
let cache = new WeakMap();
function deepClone(obj) {
// 判断基本类型 undefined null function
if (typeof obj !== "object" || !obj) return obj;
// 处理当发现缓存中有 obj 的 key 时,直接读取
if (cache.has(obj)) {
return cache.get(obj);
}
let result;
if (obj instanceof Map) {
result = new Map();
cache.set(obj, result);
obj.forEach((val, key) => {
result.set(deepClone(key), deepClone(val));
});
} else if (obj instanceof Set) {
result = new Map();
cache.set(obj, result);
obj.forEach((val) => {
result.add(deepClone(val));
});
} else if (obj instanceof Date || obj instanceof RegExp) {
result = new obj.constructor(obj);
cache.set(obj, result);
} else {
result = new obj.constructor();
cache.set(obj, result);
for (let key in obj) {
result[key] = deepClone(obj[key]);
}
}
return result;
}
const x = deepClone(obj);
console.log(x);