淺拷貝(Shallow Copy)與深拷貝(Deep Copy):深入淺出搞懂物件複製
在程式設計中,我們時常需要複製物件,但複製方式的不同,可能會導致程式出現意想不到的行為。這時,了解「淺拷貝」和「深拷貝」的差異就顯得非常重要。
事件開頭短結論:簡單來說,淺拷貝只複製物件的第一層,而深拷貝會複製物件所有層級的資料。
事件重點:
- 淺拷貝:創建一個新物件,但新物件中的物件屬性,指向原始物件中的物件。修改其中一個物件的物件屬性,會影響到另一個物件。這就像是「共享資料」。
-
深拷貝:創建一個新物件,並遞迴地複製所有層級的資料。新物件與原始物件完全獨立,修改其中一個物件的資料,不會影響到另一個物件。這就像是「各自擁有一份資料」。
深入理解
想像一個物件,它包含了基本資料型態(例如數字、字串)和其他物件。
- 淺拷貝:它會建立一個新的物件,並將原始物件的基本資料型態複製到新物件中。然而,如果原始物件中包含其他物件,淺拷貝只會複製這些物件的「參考」(記憶體位置),而不是複製物件本身。因此,新物件和原始物件中的這些物件屬性,會指向同一個記憶體位置。
-
深拷貝:深拷貝則會建立一個全新的物件,並遞迴地複製所有層級的資料。這代表,所有物件,包括嵌套的物件,都會被複製一份,並指向不同的記憶體位置。
舉例說明
假設有一個物件 obj1,包含一個數字 a 和另一個物件 b。如果我們使用淺拷貝,創建了 obj2,那麼 obj2 會有自己的 a 的副本,但 obj2.b 仍然指向 obj1.b。這表示,修改 obj1.b 裡面的屬性,obj2.b 也會跟著改變。
相反地,如果使用深拷貝,obj2 會有自己的 a 的副本,以及 obj1.b 的一個獨立副本。因此,修改 obj1.b 不會影響 obj2.b。
淺拷貝與深拷貝的應用
- 淺拷貝:
- 適用於資料結構簡單,不需要完全獨立的場景。
- 例如,複製一個設定物件,僅修改部分設定。
- 深拷貝:
- 適用於需要完全隔離資料的場景。
- 例如,建立遊戲狀態的備份、複製複雜的資料結構。
個人心得
理解淺拷貝和深拷貝,可以避免程式中出現難以追蹤的錯誤。在複製物件時,仔細思考哪種複製方式更符合需求,可以提高程式碼的穩定性和可維護性。如果需要對物件進行深層次的複製,可以使用程式語言內建的深拷貝功能或第三方函式庫,例如在JavaScript中,可以使用 structuredClone() 來進行深拷貝。
參考閱讀
- https://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy
- https://www.geeksforgeeks.org/blogs/difference-between-shallow-and-deep-copy-of-a-class/
- https://www.reddit.com/r/learnjavascript/comments/1be1oav/deep_vs_shallow_copy/
- https://www.greatfrontend.com/questions/quiz/explain-the-difference-between-shallow-copy-and-deep-copy