浅拷贝
对象类型在赋值的过程中其实是复制了地址,从而会导致改变了一方其他也都被改变的情况所以需要使用值拷贝。
首先可以通过 Object.assign 来解决
let obj={
name:'age',
age:12
}
let obj1=Object.assign({},obj)
obj1.age=13
console.log('obj:'+obj.age)
//obj:12
还有一种通过解构来拷贝
let obj={
name:'age',
age:12
}
let obj1={...obj}
obj1.age=13
console.log('obj:'+obj.age)
深拷贝
很多时候我们需要更深层次的拷贝比如向下面这样
let obj={
name:'age',
age:12,
adress:{
last:'Jiang Shu',
now:'Yan Tai'
}
}
let obj1={...obj}
obj1.adress.last='Yan Cheng'
console.log('obj:'+obj.adress.last)
//obj:Yan Cheng
而我们并不希望这种情况发生,所以有了下面这种
使用JSON.parse(JSON.stringify(obj))这种方法
let obj={
name:'age',
age:12,
adress:{
last:'Jiang Shu',
now:'Yan Tai'
}
}
let obj1=JSON.parse(JSON.stringify(obj))
obj1.adress.last='Yan Cheng'
console.log('obj:'+obj.adress.last)
在正常时候这些都够用了,但是遇到循环引用对象就不行了
下面我们使用了MessageChannel方法,注意它是一个异步的方法
function copy(obj){
return new Promise(r=>{
const {port1,port2}=new MessageChannel()
port2.onmessage=ev=>r(ev.data)
port1.postMessage(obj)
})
}
const person={
a:1,
b:{
c:3
},
e:'dsf',
}
person.b.d = person.b
async function test(){
let s=await copy(person)
console.log(s)
}
test()
但是该方法也是有局限性的:
- 会忽略 undefined
- 会忽略 symbol
- 不能序列化函数
- 不能解决循环引用的对象
- 如果需要完整拷贝需要使用 lodash 的深拷贝函数
End