淺層複製 Shallow Copy
複製一個或多個物件自身所有可數的屬性到另一個目標物件。回傳的值為該目標物件。
上面不容易理解,直接上範例比較清楚:
1 | /* 問題 */ |
- Object.assign
1 | var a = { |
Object.assign
也可改寫成 ES6
:
1 | var a = { |
然後淺層複製只會複製第一層物件,若是修改到內層物件屬性,仍會改變原本物件的屬性值
1 | var a = { |
這是因為內層的 age
仍指向原本的參考,並不會一起複製勒。
深層複製 Deep Copy
只需要將物件轉換成純值,在轉換成物件即可
- JSON.parse() with JSON.stringify()
1 | var a = { |
然而此方法僅限用於 json 格式
,屬性值不能是undefined
、NaN
或是function
,否則會無法轉換。
1 | var a = { |
深層複製完美解法
一般會參考第三方工具的深層複製寫法,當然如果是高手等級,就乾脆自己寫一個插件也不是不行。
- Underscore — _.clone()
此方法只能算是半個深層複製,也就是說不會完全複製物件內的參考。
1 | /* 請先引入 Underscore,否則會出錯 */ |
- jQuery — $.extend()
1 | /* 請先引入 jQuery,否則會出錯 */ |
注意,undefined
不會被複製到哩。
- lodash — .clone() or.cloneDeep()
_.clone(obj, true)
等於_.cloneDeep(obj)
lodash 在深層複製上更優於 jQuery、Underscore
,畢竟原始碼上就多了幾百行啊。
1 | /* 請先引入 lodash,否則會出錯 */ |
lodash的_.cloneDeep()
幾乎完美複製原本的物件內容。
效能&功能比較
特性 | jQuery | lodash | JSON.parse |
---|---|---|---|
瀏覽器兼容性 | IE6+ (1.x) & IE9+ (2.x) | IE6+ (Compatibility) & IE9+ (Modern) | IE8+ |
能夠深複製內層所有屬性值 | 回傳異常 RangeError: Maximum call stack size exceeded | 支持 | 回傳異常 TypeError: Converting circular structure to JSON |
對 Date, RegExp 的深層複製支持 | × | 支持 | × |
對 ES6 新引入的標準對象的深層複製支持 | × | 支持 | × |
複製陣列的属性 | × | 僅支持RegExp#exec返回的陣列结果 | × |
是否保留非原生對象的類型 | × | × | × |
複製不可枚舉元素 | × | × | × |
複製函數 | × | × | × |
方法 | jQuery | lodash | JSON.parse |
---|---|---|---|
平均 | 478 | 293 | 656 |
倘若需要使用到深層複製的話,還是會先以 loadsh
為優先哩。
參考資料
六角學院 - JavaScript 核心篇
JavaScript 核心觀念(30)-物件-淺層複製及深層複製
深入剖析 JavaScript 的深复制