物件結構
建立物件有兩個方式 :
- 物件實字
- 建構式物件
物件實字比起建構式更容易閱讀,也不需要額外繼承 Object()
,多數人推薦以此方式建立物件,而建構式物件則是學習建構式或者原型時再來使用。
1 | let objA = { |
物件操作(取值、新增、刪除)
取值
可以使用兩種方式來取得物件的屬性值 :
- 使用點記號來取值
.
- 必須使用字串去取得屬性名稱
- 無法使用
.數值
取得屬性值,例如obj.1
- 使用中括號與字串來取值
['屬性名稱']
,- 可以利用變數名稱帶入
1 | let b = 'a' |
新增
一樣可以透過點記號與中括號新增值。
1 | let obj = {} |
刪除
- 物件屬性可以經由
delete
刪除 - 但已宣告的變數無法透過
delete
刪除
1 | let zoo = {} |
物件與純值
物件可以新增純值,但純值無法新增屬性
1 | let cat = '阿美' |
物件與預設值
所有的變數在建立的時候,JS均會給予一個 undefined
的值,當我們賦予這個變數值時,才會是正常看到的。
1 | let a |
物件傳參考
只要看到大括號 {}
,就會與原來的物件區隔開來。
1 | // 賦予純值 |
物件複製
Call by Reference 與 Call by Sharing
在 JS中,物件是 Call by Reference 還是 Call by Sharing ?
在維基百科的求值策略中提到,JS的物件是屬於 Call by Sharing,但在取值與賦予值的過程中反而會讓人認為是其他概念。那麼,根據目的而分類它是那一種效果,而非一定是屬於那一種效果,或許比較容易理解這些概念。
Call by Reference
將原物件賦予至新變數上,修改其值後,原物件也一併被修改,因為它們參照同一個位址上的物件。
1 | const refit = (car, color) => { |
Call by Sharing
將物件複製後,修改其值,不會將原來的物件一併修改,因為使用了新物件做區隔。但這屬於淺層複製,後面會有淺層與深層複製的介紹。
1 | const refit = (car, color) => { |
Call by Value
複製 x的值給 y,y 重新賦予值不會修改 x的值
1 | let x = 1 |
淺層與深層複製
在上面的範例中,有使用到 Object.assign()
來複製物件內容,但這樣只有複製了第一層,若其中某個屬性值也是物件,也就是原物件的子物件,當修改這個子物件時,還是會修改到原物件的子內容。
淺層複製 shallow copy
1 | let carA = { |
深層複製 deep copy
藉由 JSON轉字串( JSON.stringify(物件)
)再轉回物件( JSON.parse(JSON字串)
),就能完全複製出一個新物件。
1 | let carA = { |
不過,使用 JSON互轉的方式會遇到一些問題,像是屬性值若為函式、undefined會消失,Nan則為 null。
1 | let motorcycle = { |
第三方插件的深層複製
能深層複製且沒有上述問題的方式,目前找到的有以下,經過 codePen測試(在 JS設定中匯入 CDN),可以深層複製也沒有假值的問題。
- jQuery
jQuery.extend(true, {}, 目標物件)
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js
- lodash
_.cloneDeep(objects)
https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js
非第三方插件之深層複製
若不依靠第三方插件,想自己動手試著複製,需要考慮到以下幾點,或者更多 :
- 判斷型別,typeof
- 循環引用,callback
- 建構式
- 假值判斷
- 物件相依關係
這邊附上測試後的確可運作的實例做為參考,Gary - 14. [JS] 深拷貝是什麼?如何實現?。
物件與陣列
- 物件、函式、陣列的型別都是屬於
object
- 陣列使用中括號 [ ]
- 每個索引位址都能賦予純值、物件、陣列、函式、布林值等
- 可以新增屬性,但不影響原有陣列長度
- 可以跳過索引賦予值,但是會有空的索引位置,預設為 undefined
1 | let fn = () => {return 1} |
物件與JSON
- 轉成字串時,屬性會使用雙引號
"屬性名稱"
- 撰寫 JSON格式時,無法使用物件的形式撰寫,也就是說屬性名稱必須要有單或雙引號
參考來源
- Charles Huang - JS基本觀念:call by value 還是reference 又或是 sharing?
- Ray - JavaScript 核心觀念(29)-物件-Call by Reference 還是 Call by Sharing
- huli - 深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?
- wikipedia - 求值策略
- MDN - Object.assign()
- stackoverflow - Deep copy in ES6 using the spread syntax
- jQuery - jQuery.extend()
- lodash - _.cloneDeep(value)
- Gary - 14. [JS] 深拷貝是什麼?如何實現?