1.深浅拷贝
对对象进行复制时,会出现一些问题 :
const obj = {
name: 'jack',
age: 12
}
const o = obj
console.log(o) // {name:'jack',age:12}
o.age = 20
console.log(o,obj) // {name:'jack',age:20} {name:'jack',age:20}
明明没有直接修改obj中的数据,但是里面的值却发生了变化 , 这是因为 创建对象时 , 是直接把栈中的一个地址给了obj , 这个地址指向堆中的真正对象值 , 然后又创建一个对象 o 指向了obj ,就是相当于让 o 也指向了栈中这个地址,那么在修改o中的数据时 , 对应堆中的数据会发生改变 ,再次访问 obj时 , 里面的数据就变了。所以说直接复制对象还是有很大风险的 , 这时候就需要我们的拷贝
首先 , 深浅拷贝只针对引用类型
1.1浅拷贝
常见方法 :
拷贝对象 Object.assign(o,obj) / { ...obj }
拷贝数组 Array.prototype.concat() / [ ...arr ]
const obj = {
name: 'jack',
age: 12
}
const o = { ...obj }
console.log(o) // {name:'jack',age:12}
o.age = 20
console.log(o,obj) // {name:'jack',age:20} {name:'jack',age:12}
//或者
Object.assign(o2,obj)
console.log(o2) // {name:'jack',age:12}
o2.age = 20
console.log(o2,obj) // {name:'jack',age:20} {name:'jack',age:20}
但是这样还是有问题 :
const obj = {
age: 12,
info:{
name:'jack'
}
}
const o = { ...obj }
console.log(o) // { age:12 , info: { name: 'jack' } }
o.info.name = 'lucy'
console.log(o,obj) // { age:12 , info: { name: 'lucy' }} { age:12 , info: { name: 'lucy' }}
解释一下 , 其实 这里的o.info 和 obj.info 还是指向同一个栈中的地址 , 这个栈中的地址也指的是堆中的同一个对象 , 所以在修改o.info时还是会出现问题
应该说,浅拷贝拷贝的就是值,拷贝对象的时候拷贝的是对象在栈中的地址 ,而不是地址指向的堆中的对象
1.2深拷贝
拷贝的是对象 , 不是地址
常见深拷贝方法 :
- 通过递归实现
- lodash/cloneDeep (一个js库)
- JSON.stringfy() 方法
1.递归
const obj = {
age: 12,
info:[1,2,3],
data:{ length: 1 , width: 2}
}
const o = {}
function copy(oldObj,newObj){
for(let k in oldObj){
// 这里要注意一定要先判断 Array 再判断 Object!!! 可以自己想一下为什么
if(oldObj[k] instanceof Array){
newObj[k] = [] // 意思是 newObj.k = []
copy(newObj[k],oldObj[k]) //,然后将oldObj.k(一个数组)复制给newObj ,如果数组中每一项又是数组或者对象,那么会继续迭代,此时k分别对应数组的索引号或对象里的属性名,直到所有的值都完全拷贝
}else if(oldObj[k] instaceof Object){
newObj[k] = {}
copy(newObj[k],oldObj[k])
}
// 这里的k 是每次迭代拿到的属性名 , 第一次是age ,第二次是info ......
// 新对象是空对象,不能通过newObj.k的方式来将oldObj中的k属性赋值给newObj,所以必须用obj[k]
else{
newObj[k] = oldObj[k]
}
}
}
copy(o,obj)
2.引入lodash
自行上网查找
3.JSON.strigfy
const obj = {
age: 12,
info:[1,2,3],
data:{ length: 1 , width: 2}
}
const string = JSON.stringfy(obj) //对象转 JSON字符串
const o = JSON.parse(string) //JSON字符串转对象,x相当于在栈中新建一个地址 ,堆中新开一个对象