浅拷贝和深拷贝
拷贝数据:
- 拷贝基本数据类型(String,Boolean,Number,平时主要用到的值类型),它会生产一份新的数据,对拷贝后生成的数据进行修改不会影响到原数据的;
- 拷贝引用数据类型(Array,Object,function),它不会生成新的数据,而是拷贝了一份数据在堆中的地址引用,对拷贝后生成的数据进行修改则会影响到原数据的;
- 拷贝数组或对象后,修改拷贝后的数据会影响到原来数据的拷贝被称为浅拷贝,反之称为深拷贝
let str = 'abcd';
let str2 = str;
console.log(str2);
str2 = '';
console.log(str,str2);
let bool1 = true;
let bool2 = bool1;
console.log(bool2);
bool2 = false;
console.log(bool1,bool2);
let obj1 = {username:'curry', age: '22'};
let obj2 = obj1;
console.log(obj2);
obj2.username = 'tomphson';
console.log(obj1,obj2);
let arr1 = [1,4,{username:'curry', age: '22'}];
let arr2 = arr1;
arr2[0]='abcd';
console.log(arr1);
拷贝数据的方法:
- 直接赋值给一个变量 //拷贝数组和对象就是浅拷贝
- Object.assign({},obj); //浅拷贝
- Array.prototype.concat(); //浅拷贝
- Array.prototype.slice(); //浅拷贝
- JSON.parse(JSON.stringify()); //深拷贝,但无法拷贝函数,因为stringify方法要求放入的数据是原生js对象和数组
let obj1 = {username:'tomphson', age: '22'} ;
let obj2 = Object.assign(obj1);
obj2.username = 'curry';
console.log(obj1.username);
let arr1 = [1,2,{username:'curry'}];
let arr2 = arr1.concat([]);
console.log(arr2);
arr2[1]='abcd';
arr2[2]={username:'tomphson'};
console.log(arr1);
let arr3 = arr1.slice(0,0);
arr3.username ='curry';
console.log(arr1);
let arr4 = JSON.parse(JSON.stringify(arr1));
arr4.username = 'tomphson';
console.log(arr1);
深度拷贝原理和实现
- 因为拷贝基本数据类型不会影响到原来的数据,因此我们可以根据这点遍历拷贝对象判断其数据类型直到不是引用数据类型来实现深度拷贝
let result = ['abcd'];
console.log(Object.prototype.toString.call(result));
function checkType(target) {
return Object.prototype.toString.call(target).slice(8, -1);
}
function deepClone(target) {
let targetType = checkType(target),
result;
if(targetType === 'Array') {
result = [];
}else if(targetType === 'Object') {
result = {};
}else {
result = target;
return result;
}
for(let key in target) {
let value = target[key],
valueType = checkType(value);
if( valueType === 'Array' || valueType==='Object') {
result[key] = deepClone(value);
}else {
result[key] = value;
}
}
return result;
}
let arr1 = [1,2,{username:'curry'}];
let arr2 = deepClone(arr1);
arr2.username = 'tomphson';
console.log(arr1);