工具方法
const iterableObject = Symbol('iteratorObject');
function getType(data) {
return Object.prototype.toString.call(data)
}
function handleObject(data) {
const type = getType(data);
if (type === '[object Object]' || type === '[object Array]') {
return iterableObject;
} else {
if ((typeof data === 'object' || typeof data === 'function') && data !== null) {
return new data.constructor(data);
} else {
return data;
}
}
}
递归
function deepCopy(data, hash = new WeakMap()) {
const handledData = handleObject(data);
if (handledData !== iterableObject) {
return handledData;
}
if (hash.has(data)) {
return hash.get(data)
}
const target = Array.isArray(data) ? [] : {};
hash.set(data, target);
Reflect.ownKeys(data).forEach(key => {
target[key] = deepCopy(data[key], hash)
})
return target
}
迭代
function deepCopy(data) {
const handledData = handleObject(data);
if (handledData !== iterableObject) return handledData;
const target = Array.isArray(data) ? [] : {};
const stack = [{
data,
parent: target
}];
const hash = new WeakMap();
hash.set(data, target);
while (stack.length) {
const node = stack.pop();
const {data, parent} = node;
Reflect.ownKeys(data).forEach(key => {
const value = data[key];
const handledData = handleObject(value);
if (handledData === iterableObject) {
if (hash.has(value)) {
parent[key] = hash.get(value);
} else {
parent[key] = Array.isArray(value) ? [] : {};
hash.set(value, parent[key]);
stack.push({
data: value,
parent: parent[key]
})
}
} else {
parent[key] = handledData;
}
})
}
return target;
}