JavaScript中数据类型分为基本类型和复杂类型(引用类型)
基本类型:String,Number,Boolean,undefined,null,Symbol, BigInt
复杂类型:object(包含 Array、Object、Date、RegExp等)
const clone = JSON.parse(JSON.stringify(json))
转为JSON字符串再解析为JSON对象,只能处理基本类型,丢失 function、Symbol、Date 等特殊对象。
function deepCopy(data) {
if (!data) return data
if (typeof(data) !== 'object') return data
const cloneTarget = Array.isArray(data) ? [] : {}
for (const key in data) {
cloneTarget[key] = data[key]
}
return cloneTarget
}
当象内部存在循环引用会导致深拷贝无限循环,最终导致堆栈溢出,可以用map记录已拷贝的对象,避免重复拷贝
function deepCopy(data, cache = new WeakMap()) {
if (!data) return data
if (typeof(data) !== 'object') return data
if (cache.has(data)) return data
const cloneTarget = Array.isArray(data) ? [] : {}
cache.set(data, cloneTarget)
for (const key in data) {
cloneTarget[key] = deepClone(data[key], cache)
}
return cloneTarget
}
单独处理Date、RegExp、Map、Set
function deepCopy(data, cache = new WeakMap()) {
if (!data) return data
if (typeof(data) !== 'object') return data
if (data instanceof Date) return new Date(data)
if (data instanceof RegExp) return new RegExp(data)
if (typeof obj === 'function') {
return obj.bind(null);
}
if (obj instanceof Node) {
return obj.cloneNode(true);
}
if (data instanceof Map) {
const map = new Map();
data.forEach((value, key) => map.set(key, deepClone(value, cache)));
return map;
}
if (data instanceof Set) {
const set = new Set();
data.forEach(value => set.add(deepClone(value, cache)));
return set;
}
if (cache.has(data)) return data
const cloneTarget = Array.isArray(data) ? [] : {}
cache.set(data, cloneTarget)
for (const key in data) {
cloneTarget[key] = deepClone(data[key], cache)
}
return cloneTarget
}