深入理解JS深淺拷貝

JS中數據類型

  • 基本數據類型: undefined、null、Boolean、Number、String和Symbol(ES6)
  • 引用數據類型: Object(Array, Date, RegExp, Function)

深淺拷貝

深淺拷貝只是針對引用類型的,因爲引用類型是存放在堆內存中,在棧地址有一個或者多個地址來指向推內存的某一數據

淺拷貝:

被複制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。

淺拷貝僅僅複製所考慮的對象,而不復制它所引用的對象,如果你修改了“副本”的值,那麼原來的對象也會被修改

注意:淺拷貝只進行一層拷貝

深拷貝:

深拷貝是一個整個獨立的對象拷貝,深拷貝會拷貝所有的屬性,並拷貝屬性指向的動態分配的內存。當對象和它所引用的對象一起拷貝時即發生深拷貝。深拷貝相比於淺拷貝速度較慢並且花銷較大。

深拷貝把要複製的對象所引用的對象都複製了一遍。如果你修改了“副本”的值,那麼原來的對象不會被修改,兩者是相互獨立的。

注意:深拷貝無限層拷貝

用例子看深淺拷貝

賦值實現淺拷貝

let arr = [22, 44, 66, 88];
let co = arr;
co[0] = 11;
console.log(arr, co);

結果如圖:
圖片描述

我們本來想把 arr 賦值給 co ,當我們修改co數組中第一個元素時,卻發現了原始數組arr發生了改變
很顯然,這就是一個淺拷貝的例子

原理:
對於引用類型,賦值操作符只是把存放在棧內容中的指針賦值給另外一個變量。
所以在賦值完成後,在棧內存就有兩個指針指向堆內存同一個數據。
也就可以說兩個變量在共用着同一個數據,這就是淺拷貝。

JSON實現深拷貝

let arr = [22, 44, 66, 88];
let jso = JSON.parse(JSON.stringify(arr));
jso[0] = 11;
console.log(arr, jso);

結果如圖:
圖片描述

對比之前賦值的結果,我們發現原來的數組arr並沒有被改變,可以說兩者是相互獨立的
很顯然,這就是一個深拷貝的例子

原理:
JSON.parse() 方法用於將一個 JSON 字符串轉換爲對象。
JSON.stringify() 方法用於將 JavaScript 值(通常爲對象或數組)轉換爲 JSON 字符串。
在JSON.stringify()完成後,對象就轉爲了字符串,也就可以說實實在在的複製了一個值,不存在引用之說。
再利用JSON.parse()轉爲對象,這樣達到深拷貝的目的

JSON實現深拷貝的缺陷:
來看下面例子:

let obj = {
    nul: null,
    und: undefined,
    sym: Symbol('sym'),
    str: 'str',
    bol: true,
    num: 45,
    arr: [1, 4],
    reg: /[0-9]/,
    dat: new Date(),
    fun: function() {},  
}
console.log(JSON.parse(JSON.stringify(obj)))

結果如圖:
圖片描述

我們可以發現有些屬性被忽略了:

  • undefined
  • symbol
  • function

可以看得出來JSON實現深拷貝也有不足之處

時間有限,未完待續
本篇文章接下來將會討論其他深淺拷貝的方法(如Oeject.assign(),展開運算符)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章