JS中數組的拷貝方法


  之前在寫一個vue的計算屬性時,大概是這樣:

computed: {
updateList () {
let newList = this.List
/*do something*/
return newList
},
}

  本想的是設置個中間變量newList,將它和原來的List相比做一些操作,最后返回這個newList,后來發現原List也改變了。才意識到這個newList只是個引用類型,改變了它原來的對象也會變。

  查資料的過程中,注意到了還有深拷貝淺拷貝的區別:

    淺拷貝是拷貝一層,深層次的對象級別的就只拷貝引用;

    深拷貝是拷貝多層,每一級別的數據都會拷貝出來。

一.Array的拷貝

1.淺拷貝

  如上,直接賦值的方式

2.深拷貝

(1)slice()方法

對於array對象的slice函數,返回一個數組的一段。(仍為數組)
arrayObj.slice(start, [end])

參數:
arrayObj 必選項。一個 Array 對象。
start 必選項。arrayObj 中所指定的部分的開始元素是從零開始計算的下標。
end可選項。arrayObj 中所指定的部分的結束元素是從零開始計算的下標。

說明:
slice 方法返回一個 Array 對象,其中包含了 arrayObj 的指定部分。
slice 方法一直復制到 end 所指定的元素,但是不包括該元素。
如果 start 為負,將它作為 length + start處理,此處 length 為數組的長度。
如果 end 為負,就將它作為 length + end 處理,此處 length 為數組的長度。
如果省略 end ,那么 slice 方法將一直復制到 arrayObj 的結尾。
如果 end 出現在 start 之前,不復制任何元素到新數組中。

對於本例,let newList = this.List.slice()即可

(2)concat()方法

concat() 方法用於連接兩個或多個數組。該方法不會改變現有的數組,而僅僅會返回被連接數組的一個副本。
語法:arrayObject.concat(arrayX,arrayX,......,arrayX)
說明:返回一個新的數組。該數組是通過把所有 arrayX 參數添加到 arrayObject 中生成的。如果要進行 concat() 操作的參數是數組,那么添加的是數組中的元素,而不是數組。

對於本例,let newList = this.List.concat()即可

但是,這兩種方法都有局限性,如:

var arr1 = [{"name":"weifeng"},{"name":"boy"}];//原數組
var arr2 = [].concat(arr1);//拷貝數組
arr1[1].name="girl";
console.log(arr1);// [{"name":"weifeng"},{"name":"girl"}]
console.log(arr2);//[{"name":"weifeng"},{"name":"girl"}]
var a1=[["1","2","3"],"2","3"],a2;
a2=a1.slice(0);
a1[0][0]=0; //改變a1第一個元素中的第一個元素
console.log(a2[0][0]);  //影響到了a2

var b1=[["1","2","3"],"2","3"],b2;
b2=b1.slice(0);
b1[0][0]=0; //改變a1第一個元素中的第一個元素
console.log(b2[0][0]);  //影響到了a2

從上面兩個例子可以看出,由於數組內部屬性值為引用對象,因此使用slice和concat對對象數組的拷貝,整個拷貝還是淺拷貝,拷貝之后數組各個值的指針還是指向相同的存儲地址。

因此,slice()和concat()這兩個方法,僅適用於對不包含引用對象的一維數組的深拷貝

(3)使用JSON.stringifyJSON.parse實現深拷貝:

JSON.stringify把對象轉成字符串,再用JSON.parse把字符串轉成新的對象

對於本例, let newList = JSON.parse(JSON.stringify(this.List))

JSON.stringify()有一些局限,比如不能拷貝function,詳見:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify

(4)當然,如果是不那么復雜的數組,你可以聲明一個新數組,自己寫一個for循環拷貝過去。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM