簡單一點來記的話就是在JavaScript中,原始型別(Primitive Type)的使用「看起來」像是call by value,而物件(除原始型別外全部都是)的使用「看起來」像是call by reference。
注意一點,以上說法只是描述在操作上類似於如此,而JavaScript實際上的記憶體操作是call by value reference(或稱call by sharing)。
詳細的說明或狀況,等我哪天有空我再來補補好了。
p.s. 強烈建議可以去上保哥的JavaScript 開發實戰:核心概念篇,上了課之後會有更深入的了解,雖然我也已經忘了很多...
我對不起保哥啊!
好啦~說了這麼多背景與廢話後,回到本篇主要探討的「物件複製」來看一個例子。
var originObject = {a: {c: 3,d: 4},b: 2}; var copyObject = originObject; copyObject.b = 5; console.log(originObject); //{a: {c: 3,d: 4},b: 5} console.log(copyObject); //{a: {c: 3,d: 4},b: 5} //兩個物件都中的b屬性都被更動了
可以發現,originObject以及copyObject皆指向同一塊記憶體位置,因為originObject物件中的a值也跟著改變了。
為了達成完全複製目前我所知道最方便最好用的方法就是使用jQuery的extend了。
用法如下:
var originObject = {a: {c: 3,d: 4},b: 2}; var copyObject = $.extend(true,{},originObject); //$.extend([啟用深層複製],[合併基底物件],[欲合併的物件]) copyObject.b = 5; console.log(originObject); //{a: {c: 3,d: 4},b: 2} console.log(copyObject); //{a: {c: 3,d: 4},b: 5} //可以發現只有copyObject.b被異動了
extend方法目的其實為將兩個物件做合併的動作,而這裡是將一個空物件與originObject作合併,就可以做出類似複製物件的作用啦!
至於啟用深層複製這件事,則關係到了整個物件是否為完全的複製一份,以下有個例子:
//----------------------啟用深層複製--------------------------- var originObject = {a: {c: 3,d: 4},b: 2}; var copyObject = $.extend(true,{},originObject); //使用深層複製 copyObject.a.c = 5; copyObject.b = 5; console.log(originObject); //{a: {c: 3,d: 4},b: 2} console.log(copyObject); //{a: {c: 5,d: 4},b: 5} //可以發現只有copyObject.a.c以及copyObject.b被異動了
//----------------------關閉深層複製--------------------------- var originObject = {a: {c: 3,d: 4},b: 2}; var copyObject = $.extend(false,{},originObject); //關閉深層複製 copyObject.a.c = 5; copyObject.b = 5; console.log(originObject); //{a: {c: 5,d: 4},b: 2} console.log(copyObject); //{a: {c: 5,d: 4},b: 5} //可以發現兩個物件下的屬性a中的c皆被異動了,而另外只有copyObject.b有被異動了
從例子中可以看出深層複製的真實執行結果,啟用深層複製會將整個物件,完完整整的複製一份。
而淺層複製,只有第一個層級的屬性(內容非物件類型的屬性)有被複製,而第一層屬性為物件類型的,則同樣指向同一份記憶體位置。
謝謝收看!
參考資料:
What is the most efficient way to deep clone an object in JavaScript?
http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript
[Javascript] 關於 JS 中的淺拷貝和深拷貝
http://larry850806.github.io/2016/09/20/shallow-vs-deep-copy/
[筆記] 談談JavaScript中by reference和by value的重要觀念
http://pjchender.blogspot.tw/2016/03/javascriptby-referenceby-value.html
沒有留言:
張貼留言