赋值操作:
let obj={
a:1,
b:[1,2,3],
c:{
m:2
}
}
let newObj=obj
newObj.a=2
newObj.b.push(4)
newObj.c.m=3
console.log(obj,newObj);
将一个对象赋值给一个变量,其实就是将这个对象在栈内存中的引用地址复制给了这个变量,这两个对象指向堆内存中的同一个数据引用,所以,其中一个对象的值发生变化,另一个都会跟着变化。
浅拷贝的实现方法:
1. Object.assign()
2. Array.prototype.concat()
3. Array.prototype.slice()
4. 对象和数组的扩展运算符:{...obj},[...arr]
let obj={
a:1,
b:[1,2,3],
c:{
m:2
},
}
const newObj={...obj}
obj.a=3
obj.b.push(4)
console.log(obj,newObj);
浅拷贝会在堆内存中开辟新的空间。浅拷贝只复制对象的第一层属性值,如果属性值是基本类型(如数字、字符串、布尔值),则直接复制其值;如果属性值是引用类型(如数组、对象),则复制其引用地址,而不是创建一个新的对象或数组。因此,浅拷贝后的对象和原对象共享相同的引用类型的属性值,修改其中一个对象的这些属性值会影响到另一个对象。
深拷贝实现方法:
1. JSON.parse(JSON.stringify())
let obj={
a:1,
b:[1,2,3],
c:{
m:2
}
}
let newObj=JSON.parse(JSON.stringify(obj))
newObj.a=2
newObj.b.push(4)
newObj.c.m=3
console.log(obj,newObj);// 输出结果 obj的数据没有变化
let obj={
a:null,
b:[1,2,3],
c:undefined,
fn:()=>{console.log(123);}
}
let newObj=JSON.parse(JSON.stringify(obj))
newObj.b.push(4)
console.log(obj,newObj);
JSON.parse(JSON.stringify()) 可以实现深拷贝,缺点是,如果对象或数组中有函数或undefined,就会丢失。
2. 封装深拷贝函数
let obj={
a:1,
b:[1,2,3],
c:{
m:2
},
k:undefined,
g:null,
fn:()=>{console.log(123);}
}
function deepCloneFunc(obj) {
if(typeof obj !=='object') return obj
const newObj=obj instanceof Array?[]:{}
for(let key in obj){
if(obj.hasOwnProperty(key)){
const value = obj[key]
newObj[key]=typeof value ==='object'?deepCloneFunc(value):value
}
}
return newObj
}
const newObj=deepCloneFunc(obj)
console.log(newObj);
深拷贝其实就是在堆内存中重新开辟了一块内存,创建了一个新的对象,这个对象和被拷贝的对象用于相同的属性和值,他们两个在栈内存中的引用地址也不一样,是相互独立的,因此修改任何一个对象的值,另一个都不会跟着变化。