实现
// 参数支持的数据类型
// 基础数据类型:string,number,null,undefined,Symbol,boolean
// 引用数据类型:object,array,regexp,date,set,map
function deepCopy(obj) {
// typeof + 哪些数据类型会返回 'object' ? ['object', 'array', 'regexp', 'date', 'set', 'map']
let type = Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
if (type === 'regexp') {
return new RegExp(obj);
}
if (type === 'date') {
return new Date(obj);
}
if (type === 'map') {
var cloneMap = new Map();
for (var [key, value] of obj) {
key = typeof key === 'object' ? deepCopy(key) : key;
value = typeof value === 'object' ? deepCopy(value) : value;
cloneMap.set(key, value);
}
return cloneMap;
}
if (type === 'set') {
let arr = Array.from(obj);
var cloneSet = [];
for (let item of arr) {
if (typeof item === 'object') {
cloneSet.push(deepCopy(item));
} else {
cloneSet.push(item);
}
}
return new Set(cloneSet);
}
if (['object', 'array'].includes(type)) {
var objClone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === 'object') {
objClone[key] = deepCopy(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
return objClone;
}
return obj;
}
测试
以下是针对拷贝前后的数据,取任意层级的引用数据类型属性值进行对比是否相等,或者修改新数据是否会影响原数据
var arr = [1, 2, 3];
var map = new Map();
map.set(arr, [{ a: 1, b: { c: 2 } }, 2, 1])
var obj = {
a: 1,
b: 'str',
c: NaN,
d: undefined,
e: null,
f: false,
g: Symbol('0'),
h: { aa: 22 },
i: [{ bb: 33 }, { cc: 44 }, {dd: 0}],
j: function () { },
k: /[a-z]/,
l: new Date('2012-01-03 12:00:00'),
m: new Set([{ a: 1, b: 2 }, 2, 3]),
n: map,
}
var newObj = deepCopy(obj);
// newObj.n.set(arr,[2,2,2])
console.log(obj);
console.log(newObj);
// console.log(obj.n.get(arr)[0].b === newObj.n.get(arr)[0].b);