let arr1 = [1 , 2 , 3 , "hello" , "world"]; //原数组
复制代码
拷贝数组:es6
let arr2 = arr1.slice(0);
console.log(arr2); //打印新数组
[1 , 2 , 3 , "hello" , "world"]; //新数组
复制代码
修改通过 slice() 拷贝过的新数组:数组
arr2[3] = "Hello";
console.log(arr1); //打印旧数组
[1 , 2 , 3 , "hello" , "world"]
console.log(arr2); //打印新数组
[1 , 2 , 3 , "Hello" , "world"]
复制代码
结论:使用 slice() 方法拷贝数组,而后修改新数组,不会影响到旧数组的值。浏览器
拷贝数组:bash
let arr3 = [].conat(arr1);
console.log(arr3); //打印新数组
[1 , 2 , 3 , "hello" , "world"]; //新数组
复制代码
修改通过 concat() 拷贝过的新数组ui
arr3[3] = "Hello";
console.log(arr1); //打印旧数组
[1 , 2 , 3 , "hello" , "world"]
console.log(arr3); //打印新数组
[1 , 2 , 3 , "Hello" , "world"]
复制代码
结论:使用 concat() 方法拷贝数组,而后修改新数组,不会影响到旧数组的值。spa
拷贝数组:code
let arr4 = Object.assign({} , arr1);
console.log(arr4); //打印新数组
[1 , 2 , 3 , "hello" , "world"]; //新数组
复制代码
修改通过 assign() 拷贝过的新数组对象
arr4[3] = "Hello";
console.log(arr1); //打印旧数组
[1 , 2 , 3 , "hello" , "world"]
console.log(arr4); //打印新数组
[1 , 2 , 3 , "Hello" , "world"]
复制代码
结论:使用 assign() 方法拷贝数组,而后修改新数组,不会影响到旧数组的值。递归
拷贝数组:内存
let arr5 = arr1;
console.log(arr5); //打印新数组
[1 , 2 , 3 , "hello" , "world"]; //新数组
复制代码
修改通过简单赋值过的新数组
arr5[3] = "Hello";
console.log(arr1); //打印旧数组
[1 , 2 , 3 , "Hello" , "world"]
console.log(arr5); //打印新数组
[1 , 2 , 3 , "Hello" , "world"]
复制代码
结论:使用数组简单赋值方法拷贝数组,而后修改新数组,会影响到旧数组的值。
缘由:这种简单赋值的方法属于数组的浅拷贝,数组arr1和数组arr5共用同一块内存,其中一个数组改变,另外一个数组也会跟着改变。
let arr1 = [1 , 2 , 3 , {"name" : "张小二"} , {"sex" : "male"}]; //原数组
复制代码
拷贝数组:
let arr2 = arr1.slice(0);
console.log(arr2); //打印新数组
[1 , 2 , 3 , {"name" : "张小二"} , {"sex" : "male"}]; //新数组
复制代码
修改通过 slice() 拷贝过的新数组:
arr2[3].name = "隔壁张小二";
console.log(arr1); //打印旧数组
[1 , 2 , 3 , {"name" : "隔壁张小二"} , {"sex" : "male"}]
console.log(arr2); //打印新数组
[1 , 2 , 3 , {"name" : "隔壁张小二"} , {"sex" : "male"}]
复制代码
结论:使用 slice() 方法拷贝数组,而后修改新数组,会改变旧数组的值。
拷贝数组:
let arr3 = [].conat(arr1);
console.log(arr3); //打印新数组
[1 , 2 , 3 , {"name" : "张小二"} , {"sex" : "male"}]; //新数组
复制代码
修改通过 concat() 拷贝过的新数组
arr3[3].name = "隔壁张小二";
console.log(arr1); //打印旧数组
[1 , 2 , 3 , {"name" : "隔壁张小二"} , {"sex" : "male"}]
console.log(arr3); //打印新数组
[1 , 2 , 3 , {"name" : "隔壁张小二"} , {"sex" : "male"}]
复制代码
结论:使用 concat() 方法拷贝数组,而后修改新数组,会改变旧数组的值。
拷贝数组:
let arr4 = Object.assign({} , arr1);
console.log(arr4); //打印新数组
[1 , 2 , 3 , {"name" : "张小二"} , {"sex" : "male"}]; //新数组
复制代码
修改通过 assign() 拷贝过的新数组
arr4[3].name = "隔壁张小二";
console.log(arr1); //打印旧数组
[1 , 2 , 3 , {"name" : "隔壁张小二"} , {"sex" : "male"}]
console.log(arr4); //打印新数组
[1 , 2 , 3 , {"name" : "隔壁张小二"} , {"sex" : "male"}]
复制代码
结论:使用 assign() 方法拷贝数组,而后修改新数组,会改变旧数组的值。
一、数组的浅拷贝
(1)数组的直接赋值属于数组的浅拷贝,JS存储对象都是存内存地址的,因此浅拷贝会致使新数组和旧数组共用同一块内存地址,其中一个数组变化,另外一个数组也会相应的变化。
(2)数组内部不含有引用类型,使用slice() 、concat() 和 assign() 方法都属于数组的深拷贝,一个数组变化,另外一个数组不受影响。
(3)数组内部含有引用类型,使用slice() 、concat() 和 assign() 方法,非引用类型的值属于深拷贝,引入类型的值属于浅拷贝,一个数组变化,另外一个也会相应的变化。
方法一:递归
let cloneObj = function(obj){
let str, newobj = obj.constructor === Array ? [] : {};
if(typeof obj !== 'object'){
return;
} else if(window.JSON){
str = JSON.stringify(obj), //系列化对象
newobj = JSON.parse(str); //还原
} else {
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ?
cloneObj(obj[i]) : obj[i];
}
}
return newobj;
};
let newArr = cloneObj(oldArr);
复制代码
方法二:经过JSON解析解决
let newArr = JSON.parse(JSON.stringify(oldArr));
复制代码
注意:这种方法拷贝后的数组会丢失原数组中定义的方法和数组原型中定义的方法。