在JS中存在两种数据类型
1. 基本类型
2.引用类型
基本类型存放在栈中,而引用类型存放在堆中
当我们将一个变量赋值给另一个变量时,需要先进行判断是什么类型
基本类型的话,会将新变量存储在栈中,并将旧变量的值复制给新变量
但是引用类型的话,变量存放的是指向堆内存对象的地址,在赋值时会把引用地址复制过去,这就会导致新变量修改后,旧变量也会发生改变
因此在引用类型数据进行赋值时,就需要做出处理
1. 浅拷贝:
只拷贝对象一层数据,深层次的数据依旧共享内存地址
通过扩展运算符进行浅拷贝,对age和address.city进行修改赋值,但是obj1的age并没有发生变化,而深层次的city变化了。
const obj1={
name:'张三',
age:18,
address:{
city:'北京'
},
hobby:["台球","篮球"]
}
const obj2={...obj1}
obj2.address.city='上海'
obj2.age=20
console.log(obj1.age) //18
console.log(obj1.address.city) //上海
浅拷贝还有其他方法,例如:Object.assign(),concat(),slice()等
扩展运算发和Object.assign()缺点:
不会拷贝对象的继承属性,不会拷贝对象的不可枚举属性,可以拷贝symbol类型的属性
浅拷贝的实现
function shallowClone(obj){ //浅拷贝
if(typeof obj!=='object'||obj==null){
return obj
}
const newObj=obj instanceof Object?{}:[]
for(let key in obj){
newObj[key]=obj[key]
}
return newObj
}
2.深拷贝:
开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
深拷贝实现
function deepClone(obj){ //深拷贝
if(typeof obj!=='object'||obj==null){
return obj
}
const newObj=obj instanceof Object?{}:[]
for(let key in obj){
if(obj.hasOwnProperty(key)){
newObj[key]=deepClone(obj[key])
}
}
return newObj
}
进行深拷贝之后,对obj3进行深层次的属性修改,原对象都不会发生改变
const obj3=deepClone(obj1)
obj3.address.city='上海'
console.log(obj1.address.city) //北京
实现深拷贝的其他方法:
1.JSON.parse(JSON.stringfy(obj))
缺点:不能存放函数、时间对象、正则
2.lodash.cloneDeep