在JS的專案中很常會使用到物件,那物件就很容易會複製來複製去的,很容易會因為js的物件參照特性而有一些bug,那這一偏就來記錄一下,淺層拷貝和
深層拷貝的關係跟使用方法。
深層拷貝 代表新的變數的值 跟 原本的變數值 沒有任何關係。
淺層拷貝 代表新的變數的值 跟 原本的變數值還是有關係。
淺層拷貝
JS的物件操作是call by reference,所以,當我們直接將某個物件複製給另一個變數時,會因為這他們都指向同一個記憶體位置,集他們都共用同一個物件內容,
此種狀況即為淺拷貝。
1 | let obj1 = { value:10 } |
深層拷貝
那我們可以用什麼方法達到深層複製呢? 使用Object.assign({}, oringinObj) 或者 使用 ES6的展開語法。
ex1: (Object.assign 用法)
1 | let obj1 = { value:10 } |
ex2: (ES6的展開語法)
1 | let obj1 = { |
Object.assign和ES6 展開語法的問題
但是,用這種深層拷貝的方法,在原物件第二層的成員屬性還是有淺層拷貝的問題。
1 | let obj1 = { |
消除深層拷貝的問題-用JSON轉型
1 | let obj1 = { |
JSON轉型-深層拷貝的問題
雖然,上面的例子看起來JSON轉型有辦法解決深層拷貝的問題,但是,當原物件中的成員屬性值為NaN
或undefined
,或者,成員屬性是function
,
JSON轉型的是沒辦法拷貝以上這些成員的,而NaN
的值會被轉成null
。
那最終的辦法還是建議用框架,例如 jQuery 的 $.extend
就可以做到完整的深層拷貝。
1 | let obj1 = { |
參考資料
- https://www.javascripttutorial.net/object/3-ways-to-copy-objects-in-javascript/
- https://medium.com/@yining1204/javascript-%E6%A0%B8%E5%BF%83%E7%AF%87-%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-chap-38-%E6%B7%BA%E5%B1%A4%E8%A4%87%E8%A3%BD%E5%8F%8A%E6%B7%B1%E5%B1%A4%E8%A4%87%E8%A3%BD-c237fd383864
- https://hsiangfeng.github.io/javascript/20200905/1375484447/