本质:值的改变会不会相互影响
1.对于原始数据类型,复制之后再改变值,不会相互影响。属于深拷贝
let a=5
let b=a
a=6
console.log(a,b)
得到结果,6 5
2.对于引用数据类型,因为在复制的时候是按值传递,所以其中任意一方值改变,会相互造成影响。属于浅拷贝
解决:两个独立的引用地址
对于对象的深拷贝,可以使用JSON.parse与JSON.stringify转化一下。
let str=JSON.stringify(obj1)
let obj2=ISON.parse(str)
这样得到的obj2与obj1互不影响。
注:ES6中API Object.assign()所实现的也是浅拷贝,它的本质是将地址赋值给目标对象。
3.对于复杂数据类型
3.1只考虑数组和对象
//1.检查类型
let checkType=data=>{
return Object.prototype.toString.call(data).slice(8,-1)
}
//2.clone
let deepClone=target=>{
//2.1判断类型
let targetType=checkType(target)
let result
if(targetType==='Object'){
result={}
}else if(targetType==='Array'){
result=[]
}else{
return target
}
//2.2循环遍历
for(let i in target){
let value=target[i]
let valueType=checkType(value)
if(valueType==='Object' || valueType==='Array'){
result[i]=deepClone(value) //递归
}else{
result[i]=value
}
}
return result
}
let arr1=[1,2,{a:12},[3,4]]
let arr2=deepClone(arr1)
arr2[2].a=90
console.log(arr1)
console.log(arr2)
结果
注:该方法参考imooc课程
3.2多类型考虑,包括null
function clone(obj) {
if(obj===null){
return null
}
if({}.toString.call(obj)==='[object Array]'){
var newArr=[]
newArr=obj.slice()
return newArr
}
var newObj={}
//遍历原obj的每个属性
for(var key in obj){
if(typeof obj[key]!=='object'){
newObj[key]=obj[key]
}else{
newObj[key]=clone(obj[key])
}
}
}
var obj3=[1,2,null,[3,5],{a:1,b:null}]
var obj4=clone(obj3)
console.log(obj3)
console.log(obj4)
结果
注:该方法参考达内张东视频