浅拷贝:此处浅拷贝是针对对象的,因为如果是基本数据类型,直接赋值就可以拷贝。拷贝对象时,若属性是基本数据类型则拷贝值,若属性是引用数据类型,则拷贝地址值,但会导致修改新数据会同时修改原数据,因为新数据和原数据共享内存。
浅拷贝方法:
1、三点运算符:var copyarr=[...arr]
2、Object.assign方法:Object.assign(copyarr,arr1,arr2,...)
3、数组的Array.prototype.concat方法:var copyarr=arr.concat()
4、数组的Array.prototype.slice方法:var copyarr=arr.slice()
深拷贝:精确拷贝,深入拷贝到对象里的基本数据类型,从而当对象数据发生变化而不影响原数据
深拷贝方法
1、利用JSON
JSON.parse(JSON.stringify(obj/arr))
问题:
- 若原数据包含函数,undefined,symbol等属性,拷贝后这些属性会消失
- Date对象会变成String类型,RegExp对象会变成空对象{}
- 对象中含有NaN、Infinity和-Infinity,拷贝后会变成null
- 未拷贝对象的原型链
2、采用递归
简单版:只考虑数组和对象
function clone(obj){
if(typeof obj === 'object'&&obj!==null){
var newObj = Array.isArray(obj)?[]:{}
for(const key in obj){
newObj[key]=clone(obj[key])
}
return newObj
}
else return obj
}
问题:
- 未拷贝正则对象和Date对象
- for in可能会拷贝到原型对象的属性
- 未继承原型链
优化
function clone(obj){
if(obj instanceof RegExp){
return new RegExp(obj)
}
else if(obj instanceof Date){
return new Date(obj)
}
else if(obj instanceof Array){
let newObj=[]
obj.forEach((value)=>{
newObj.push(clone(value))
})
return newObj
}
else if(obj instanceof Object){
//拷贝原型链
let newObj=new obj.contructor()
for(let key in obj){
//判断是否是该对象上的属性,而非继承的属性
if(obj.hasOwnProperty(key)){
newObj[key]=clone(obj[key])
}
}
return newObj
}
return obj
}