JS實現二維陣列的深拷貝及外掛程式碼
深拷貝與淺拷貝的介紹
在寫程式碼前先簡短介紹下JS中淺拷貝與深拷貝的區別。
JavaScript中有兩種型別的物件拷貝:淺拷貝(Shallow Copy)、深拷貝(Deep Copy):
深複製和淺複製最根本的區別在於是否是真正獲取了一個物件的複製實體,而不是引用。
淺拷貝——只是拷貝了基本型別的資料,而引用型別資料,複製後也是會發生引用,我們把這種拷貝叫做“淺拷貝(淺複製)”,也就是說,淺複製僅僅是指向被複制的記憶體地址,如果兩者中任一物件被改變了,那麼另一個物件也會相應改變。
深拷貝——在計算機中開闢了一塊新的記憶體地址用於存放複製的物件。
由此引出的問題
深拷貝和淺拷貝在複製物件為number時並沒有什麼問題,但當我們直接複製陣列時就會引起下列的問題:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>deep-copy</title> </head> <body> <script type="text/javascript"> var arr = [1,2,3,4,5,6]; var copyarr=new Array; copyarr = arr; arr[0]= "heihei"; document.write("arr"+"="+arr); document.write("<br>") document.write("copyarr"+"="+copyarr); </script> </body> </html>
下面是執行結果:
很多時候,我們拷貝一個數組得到一個拷貝陣列,是想對拷貝陣列或者原陣列進行一些操作而不想引起另一個數組發生改變,但是由於JS中深淺拷貝的存在,我們直接將原陣列賦值給拷貝陣列,這種操作相當於是把一個指向該陣列的指標賦值給了拷貝陣列,得到的是一個新指標(雖然在JS中講指標並不合適但是在此用指標十分形象),屬於淺拷貝,達不到我們要的效果。
這裡很直觀的我們會想到,利用for迴圈遍歷陣列一個個給拷貝陣列賦值,發現確實兩者不會相互改變,但還是屬於淺拷貝,為什麼這麼說吶,因為當陣列為二維(陣列中包含陣列)或者更高維度時,我們又遇到了前面的問題,因為三維及以上陣列在實際中並不實用,所以下面介紹的陣列深拷貝程式碼並不考慮三維及以上(其實實現也很簡單,利用函式的淺拷貝然後判斷是否i位為陣列再進行淺拷貝的遞迴功能即可)。
二維陣列的深拷貝
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<script type="text/javascript">
// 定義一個名為newCopy的函式(函式名字可以隨意改,使用函式時改成你改的名字即可)
function newCopy(arr) {
// 在函式內使用var宣告一個拷貝陣列用於拷貝
var copyArr = new Array;
for (i = 0; i < arr.length; i++) {
// 判斷第i位是否為陣列(二維)
if (typeof arr[i] == "object") {
// 若第i位是陣列我們就將copyArr的第i位也置為陣列(這裡使用
var宣告會出錯,因為copyArr[i]並不是一個變數)並用for迴圈賦值
copyArr[i] = new Array();
for (j = 0; j < arr[i].length; j++) {
copyArr[i][j] = arr[i][j];
}
// 如果不是陣列則直接賦值
} else {
copyArr[i] = arr[i];
}
}
// 返回我們的拷貝陣列
return copyArr;
}
// 以下可以用來檢測是否為二維陣列深拷貝
// var arr=[[1,2,30],2,5,8,7]
// var copyArr=newCopy(arr);
// arr[0][2]="heihie";
// copyArr[0][1]="ha";
// document.write(arr);
// document.write("<br>");
// document.write(copyArr);
</script>
</body>
</html>
上面的程式碼已經封裝好了,可以直接複製到JS裡面就可以直接使用該函式外掛達到二維陣列的深拷貝效果。
我們可以將最下面的註釋啟用來驗證可行性,得到的效果如下:
可以發現實現了二維陣列的深拷貝,兩者改變自己互不影響。希望能幫到大家!