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));
複製代碼
注意:這種方法拷貝後的數組會丟失原數組中定義的方法和數組原型中定義的方法。