综述:一个简单的问题,其实有些细节需要好好总结下
1.浅拷贝的方法
- es6 扩展运算符...
用扩展运算符对数组或者对象进行拷贝时,只能扩展和深拷贝第一层的值,对于第二层极其以后的值,扩展运算符将不能对其进行打散扩展,也不能对其进行深拷贝,即拷贝后和拷贝前第二层中的对象或者数组仍然引用的是同一个地址,其中一方改变,另一方也跟着改变,这里就属于浅拷贝。
- Object.assign() 只能实现对象第一层级的浅拷贝
- 直接使用等号只能实现基本数据类型的浅拷贝
2.深拷贝的几种方式
- JSON.parse(JSON.stringify(obj)),当obj中存在new Date 时,会转成一个字符串时间, 函数对象时,也会转成一个新的字符串, 正则表达式时也会转成字符串,会存在bug。
- 使用lodash库的deepClone方法
- 自己写一个深拷贝方法,对1中说明的特殊情况进行转换
function deepClone(obj){
if(obj===null) return obj;
if(typeof obj!=='object') return obj;
/* 重新new是为了让他做一个复制操作,而不是原来的值返回,没有达到深拷贝的目的 */
if(obj instanceof RegExp){
return new RegExp(obj);
}
/* 重新new是为了让他做一个复制操作,而不是原来的值返回,没有达到深拷贝的目的 */
if(obj instanceof Date){
return new Date(obj);
}
// 这里的newObj不使用{},是为了保证克隆的结果和之前的保持相同的所属类,比如传进来的
let newObj =new obj.constructor()
for(let key in obj){
//hasOwnProperty表示是否有自己的属性。这个方法会查找一个对象是否有某个属性,但是不会去查找它的原型链
if(obj.hasOwnProperty(key)){
console.log(obj[key],key,'key')
newObj[key] = deepClone(obj[key])
}
}
return newObj;
}
const testObj = {a:1,b:{c:new Date(),d: function(){console.log(6666)}}}
console.log(deepClone(testObj))
console.log(JSON.parse(JSON.stringify(testObj)))