深拷贝
前提
- 基本数据类型有:number,string,boolean,null,undefined,symbol,BigInt;
- 引用数据类型:object,array,function等;
- 基本数据类型存储在栈内存中,当复制时,栈内存会新开辟一个内存,即对于基本类型的数据,是拷贝值,不会拷贝引用;
- 对于引用类型的数据,它们的名字存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值,当复制时,其实复制的是引用地址,而非堆里面的值,所以我们要在堆内存中也开辟一个新的内存存放拷贝值,(调用他们的构造函数,创建一个新的引用,之后遍历原引用类型中的所有属性,递归拷贝);
- 在写之前先定义一个引用数据类型,以下的测试都可以用这个数据
const obj = {
name:'张三',
info: {
age: 20,
sex: 'male',
fancy:['唱歌','跳舞']
}
}
JSON 方法
- 不支持值为undefined、函数和循环引用的情况;
const cloneObj = JSON.parse(JSON.stringify(obj))
递归法拷贝
function deepCopy(obj, cache = new WeakMap()) {
if(obj === null || typeof obj !== 'object') return obj
if(obj instanceof Date) return new Date(obj)
if(obj instanceof RegExp) return new RegExp(obj)
if(cache.has(obj)) return cache.get(obj)
let newObj = new obj.constructor()
cache.set(obj, newObj)
for(let key in obj) {
if(obj.hasOwnProperty(key)) {
newObj[key] = deepCopy(obj[key], cache)
}
}
return newObj
}
function deepCopy(obj) {
if(obj === null || typeof obj !== 'object') return obj
if(Object.prototype.toString.call(obj) === "[Object Date]") return new Date(obj)
if(Object.prototype.toString.call(obj) === "[Object RegExp]") return new RegExp(obj)
if(Object.prototype.toString.call(obj) === "[Object Undefined]") return new Error(obj)
let newObj = Array.isArray(obj) ? [] : {}
for(let key in obj) {
if(typeof obj[key] === 'object'){
newObj[key] = deepCopy(obj[key])
}else{
newObj[key] = obj[key]
}
}
return newObj
}
function deepCopy(obj) {
if(obj === null || typeof obj !== 'object') return obj
let cache = null
if(!deepCopy.cache) deepCopy.cache = new WeakMap()
cache = deepCopy.cache
if(cache.has(obj)) return cache.get(obj)
if(obj instanceof Set) {
const temp = new Set()
cache.set(obj, temp)
obj.forEach(item => {
temp.add(deepCopy(item))
})
return temp
}else if(obj instanceof Map) {
const temp = new Map()
cache.set(obj, temp)
obj.forEach(item => {
temp.set(key, deepCopy(item))
})
return temp
}else if(obj instanceof RegExp) {
return new RegExp(obj)
}else if(obj instanceof Date) {
return new Date(obj)
}else{
const temp = new obj.constructor()
cache.set(obj, temp)
for(let key in obj) {
temp[key] = deepCopy(obj[key])
}
return temp
}
}