区别其他深拷贝实现--用上解构能够保持数据一致性-而不像JSON.parse(JSON.stringify())实现会导致一些数据发生变化:比如时间对象new Date()会变成字符串,error对象/函数会变成{}等
浅拷贝用展开符就行let newObj={...cloneObj}
let a = {
name: [
{
secName: undefined,
errName: new Error(),
thirdName: () => { },
secArr: [
{
test: {
swim: 123
}
},
[ { name: 12345 } ]
]
}
],
doubleObj: {
thirdObj: 2134
}
}
/**核心代码-start**/
const deepClone=(newcurr)=>{
newcurr={...newcurr}
for (const key in newcurr) {
if(newcurr[key] instanceof Object){
newcurr[key]=deepClone(newcurr[key])
}
}
return newcurr
}
/**核心代码-end**/
考虑完整情况比如循环引用/递归爆栈可以参考现有方案 主要是采用栈+while替代递归/map结构来看是否集中缓存来返回引用
const { toString, hasOwnProperty } = Object.prototype;
function hasOwnProp(obj, property) {
return hasOwnProperty.call(obj, property)
}
function getType(obj) {
return toString.call(obj).slice(8, -1).toLowerCase();
}
function isObject(obj) {
return getType(obj) === "object";
}
function isArray(arr) {
return getType(arr) === "array";
}
function isCloneObject(obj) {
return isObject(obj) || isArray(obj)
}
function cloneDeep(x) {
let uniqueData = new WeakMap();
let root = x;
if (isArray(x)) {
root = [];
} else if (isObject(x)) {
root = {};
}
// 循环数组
const loopList = [ { parent: root, key: undefined, data: x, } ];
while (loopList.length) {
// 深度优先
const node = loopList.pop();
const parent = node.parent;
const key = node.key;
const source = node.data;
// 初始化赋值目标,key为undefined则拷贝到父元素,否则拷贝到子元素
let target = parent;
if (typeof key !== 'undefined') {
target = parent[key] = isArray(source) ? [] : {};
}
// 复杂数据需要缓存操作
if (isCloneObject(source)) {
// 命中缓存,直接返回缓存数据
let uniqueTarget = uniqueData.get(source);
if (uniqueTarget) {
parent[key] = uniqueTarget;
continue; // 中断本次循环
}
// 未命中缓存,保存到缓存
uniqueData.set(source, target);
}
if (isArray(source)) {
for (let i = 0; i < source.length; i++) {
if (isCloneObject(source[i])) {
// 下一次循环
loopList.push({
parent: target,
key: i,
data: source[i],
});
} else {
target[i] = source[i];
}
}
} else if (isObject(source)) {
for (let k in source) {
if (hasOwnProp(source, k)) {
if (isCloneObject(source[k])) {
// 下一次循环
loopList.push({
parent: target,
key: k,
data: source[k],
});
} else {
target[k] = source[k];
}
}
}
}
}
uniqueData = null;
return root;
}