1.背景介紹
javascript分原始型別與引用型別。Array是引用型別,直接用“=”號賦值的話,只是把源陣列的地址(或叫指標)賦值給目的陣列,指向的是同一個記憶體地址,其中一個改變另一個也會改變。並沒有實現陣列的資料的拷貝。這種方式的實現屬於淺拷貝。
深拷貝是開闢新的儲存空間,兩個物件對應兩個不同的地址,修改一個物件的屬性,不會改變另一個物件的屬性。
2.使用方法
陣列淺拷貝:
var arr1 = [1, 2, 3, 4]; var arr2 = arr1; arr1[0] = 6; //陣列是用堆去儲存的,相等的時候只是把存放的地址拷貝過去了,兩個指向了同一個地址,所以在改變其中一個的值,其他的也跟著改變了 console.log(arr2[0]); //輸出結果為6 console.log(arr1); //[6, 2, 3, 4] console.log(arr2); //[6, 2, 3, 4]
陣列深拷貝:
1.JSON.stringify和JSON.parse方法
var arr1 = [1, 2, 3, 4];
var arr2 = JSON.parse(JSON.stringify(arr1)) //先將陣列轉為字串,然後轉成js物件
arr1[0] = 6;
console.log(arr2[0]); //輸出結果為1
console.log(arr1); //[6, 2, 3, 4]
console.log(arr2); //[1, 2, 3, 4]
2.slice方法
var arr1 = [1, 2, 3, 4]; var arr2 = arr1.slice(0); //從0開始到末尾擷取陣列,然後返回一個新的陣列 arr1[0] = 6; console.log(arr2[0]); //輸出結果為1 console.log(arr1); //[6, 2, 3, 4] console.log(arr2); //[1, 2, 3, 4]
3.concat方法
var arr1 = [1, 2, 3, 4]; var arr2 = arr1.concat(); //連線陣列,如果連線的是一個空,那麼也是返回了新的本身的陣列 arr1[0] = 6; console.log(arr2[0]); //輸出結果為1 console.log(arr1); //[6, 2, 3, 4] console.log(arr2); //[1, 2, 3, 4]
4.map方法
var arr1 = [1, 2, 3, 4]; var arr2 = arr1.map(function(value){ return value; }) //使用map方法遍歷陣列然後返回新的陣列,裡面的值不變 arr1[0] = 6; console.log(arr2[0]) //輸出結果為1 console.log(arr1); //[6, 2, 3, 4] console.log(arr2); //[1, 2, 3, 4]
5.ES6語法
var arr1 = [1, 2, 3, 4]; var [ ...arr2 ] = arr1; //ES6擴充套件運算子實現陣列的深拷貝 arr1[0] = 6; console.log(arr2[0]); //輸出結果為1 console.log(arr1); //[6, 2, 3, 4] console.log(arr2); //[1, 2, 3, 4]
6.用for迴圈遍歷複製
var arr1 = [1, 2, 3, 4];
var arr2 = [];
for(i=0;i<arr1.length;i++){
arr2.push(arr1[i])
}
arr1[0] = 6;
console.log(arr2[0]); //輸出結果為1
console.log(arr1); //[6, 2, 3, 4]
console.log(arr2); //[1, 2, 3, 4]
簡單來說,深拷貝主要是將另一個物件的屬性值拷貝過來之後,另一個物件的屬性值並不受到影響,因為此時它自己在堆中開闢了自己的記憶體區域,不受外界干擾。
淺拷貝主要拷貝的是物件的引用值,當改變物件的值,另一個物件的值也會發生變化。
那具體使用情況該使用淺拷貝還是深拷貝呢,沒有一成不變的規則,一切都取決於具體需求~