第151题 手写JS深拷贝-考虑各种数据类型和循环引用
- 使用JSON.stringify
- 无法转换函数
- 无法转换
Map和Set - 无法转换循环引用
- 普通深拷贝
- 只考虑
Object和Array - 无法转换
Map、Set和循环引用 - 只能应对初级要求的技术一面
- 只考虑
普通深拷贝 - 只考虑了简单的数组、对象
/**
* 普通深拷贝 - 只考虑了简单的数组、对象
* @param obj obj
*/
function cloneDeep(obj) {
if (typeof obj !== 'object' || obj == null ) return obj
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = cloneDeep(obj[key]) // 递归调用
}
}
return result
}
// 功能测试
const a: any = {
set: new Set([10, 20, 30]),
map: new Map([['x', 10], ['y', 20]])
}
a.self = a
console.log( cloneDeep(a) ) // 无法处理 Map Set 和循环引用
深拷贝-考虑数组、对象、Map、Set、循环引用
/**
* 深拷贝
* @param obj obj
* @param map weakmap 为了避免循环引用、避免导致内存泄露的风险
*/
function cloneDeep(obj, map = new WeakMap()) {
if (typeof obj !== 'object' || obj == null ) return obj
// 避免循环引用
const objFromMap = map.get(obj)
if (objFromMap) return objFromMap
let target = {}
map.set(obj, target)
// Map
if (obj instanceof Map) {
target = new Map()
obj.forEach((v, k) => {
const v1 = cloneDeep(v, map)
const k1 = cloneDeep(k, map)
target.set(k1, v1)
})
}
// Set
if (obj instanceof Set) {
target = new Set()
obj.forEach(v => {
const v1 = cloneDeep(v, map)
target.add(v1)
})
}
// Array
if (obj instanceof Array) {
target = obj.map(item => cloneDeep(item, map))
}
// Object
for (const key in obj) {
const val = obj[key]
const val1 = cloneDeep(val, map)
target[key] = val1
}
return target
}
// 功能测试
const a: any = {
set: new Set([10, 20, 30]),
map: new Map([['x', 10], ['y', 20]]),
info: {
city: 'shenzhen'
},
fn: () => { console.info(100) }
}
a.self = a
console.log( cloneDeep(a) )
