1. 程式人生 > 其它 >JavaScript:物件:如何複製一個物件?淺拷貝與深拷貝

JavaScript:物件:如何複製一個物件?淺拷貝與深拷貝

回顧一下,我們對傳參的討論,物件的傳參是引用傳遞,我們傳遞的是物件資料所在的記憶體地址;

那麼無論我們怎麼去賦值,所有變數指向的都是同一塊記憶體;

如上圖所示,無論我去使用哪個變數去操作物件的屬性,改變的始終是同一塊記憶體區域的資料;

現在,我希望可以將obj1的記憶體資料,完整複製一份,存放到另一個記憶體區域obj2,使得這兩塊記憶體,儲存的資料內容完全一樣,但是我改變其中一塊記憶體的資料,都不會影響到另一塊記憶體的資料;

想一想,我們應該怎麼做,才能達到這一目的?

淺拷貝

能想到的,是遍歷物件的屬性(基本資料型別),然後依次賦值給另一個物件的屬性,因為說到複製,就是指值傳遞,只有基本資料型別是值傳遞:

如上圖所示,我們遍歷了obj1的屬性,並賦值給了obj2,我們修改了obj2的name1屬性,但是並沒有改變obj1的name1屬性,證明我們成功複製了一份obj1的記憶體資料;

那我們每次都需要用for-in迴圈嗎?JS有沒有自帶一些方法來實現淺拷貝呢?

有的:

  • Object.assign()方法

    語法為Object.assign(dest, src1, src2,,,,,)

    第一個變數dest是目標物件,即將後面的物件的屬性值複製給目標物件;

    後面的所有變數src即是源物件,會將所有源物件的屬性值全複製給目標物件,如果有屬性名同名,則會進行覆蓋;

    呼叫該方法,結果會返回dest;

深拷貝

現在假設,obj1中,name1是一個物件型別,上面的拷貝方式,還行得通嗎?

看上圖,obj2對name1的name屬性修改為了Bob,而obj1的name1的name屬性,輸出結果也為Bob,這意味著,obj1和obj2的name1屬性指向的是同一塊記憶體區域;

這是因為,物件是引用傳遞,我們在呼叫Object.assign()方法時,只是將obj1的name1的記憶體地址,複製給了obj2的name1,此時他們之間的記憶體關係,如下所示:

也就是說,此時obj1和obj2並不完全互相獨立,他們之間還共同管理著name1這塊記憶體;

這種不完全互相獨立的拷貝,我們稱之為淺拷貝

所以,完全互相獨立的拷貝,我們就稱之為深拷貝

那麼,我們怎樣才能實現深拷貝,使兩者完全互相獨立呢?

可行的方法是,對name1這個物件,再進行一次淺拷貝。

這樣太麻煩了,JS有沒有自帶的深拷貝的方法呢?

很遺憾,並沒有。我們需要通過引入其他庫,呼叫庫方法,來進行深拷貝,這裡不贅述。