Bukle Script Object
Javascript 中的物件有兩個主要的目的
- 像是一個雜湊表(或是字典), Keys 可以動態的 新增/刪除 ,值是同樣的型態
- 像是一個紀錄(Record),欄位是固定的(但是也允許是選擇性的),他的值可以是不同的形態
這部分 BuckleScript 的物件也是一樣的
雜湊表模式
直到最近 Javascript
才終於有正確的支援 Map
物件使用上和 Map
可以是一樣的
前提是
- 可能會或是不會 新增/刪除 參數的鰎值
- 值可以被 動態/計算 鍵值 瀏覽
- 值得型態都是一樣
這時候可以利用 Js.Dict
來綁定這個 Javascript 物件
你可以就像 Javascript 中的 Object 來做操作
Js.Dict.keys
來取得所有的鍵值
Js.Divt.values
來取得所有的值
範例
1 | let myMap = Js.Dict.empty(); |
轉譯後的結果
1 | ; |
你可以看到其實 Js.Dict
是基於 Javascript 的物件
整個 API 都沒有使用到 external
所以在編譯之後 整個 API 都會消失
編譯結果中你也找不到 Dict
的相關字
這很便於你將 Js 檔案轉為 BuckleScript 檔案
Record 模式
如果你的 Js 物件:
- 有固定並且已知的欄位
- 包含的值有不同的型別
這時候大多數的程式語言中 你都可以使用 Record
例如:
1 | { |
和
1 | { |
的不同
前者會使用 雜湊表
的型態來處理
後者會使用 Record
來處理
而在 BuckleScript 中要使用 bs.deriving abstract
功能
後者則會這樣寫
1 | [@bs.deriving abstract] |
note person
並不是一個 Record
的型別
他只是看起來像是 Record
的型別
而且可以使用 Record
的形態檢查
bs.deriving abstract
就是在註解將 person
轉為 抽象型別
建立
上述的抽象型別因為不是 Record
型別
所以不能直接使用型態的方式來建立
1 | [@bs.deriving abstract] |
轉譯後的結果
1 | // Generated by BUCKLESCRIPT VERSION 4.0.5, PLEASE EDIT WITH CARE |
結果對於運行並不會有成本
欄位重新命名
有時候在綁定 JS object 的時候,欄位名稱在 BuckleScript/Reason 中是無效的名稱
有兩種範例 一個是 {type: "foo"}
(BS/Reason 中的保留字) 和 {"aria-checked": true}
可以選擇另一個有效的名稱 使用 @bs.as
來規避這個問題
1 | [@bs.deriving abstract] |
輸出會是
1 | ; |
可選的標籤
可以建立可忽略的 欄位
1 | [[@bs.deriving abstract] |
編譯後會是
1 | var Js_primitive = require("bs-platform/lib/js/js_primitive.js"); |
可以看到 name
會是可選的,若是沒有也不會造成錯誤
note:bs.optional 只是將 name 改為可選,但是如果輸入 Option(string) 不會有作用
Accessors
當你使用 bs.deriving abstract
隱含了 recode 的型態,你無法使用 joe.age
這樣的方式來取得值
原生會提供 getter
和 setter
來完成這個
取值
每一個 bs.deriving abstract
欄位 都會有一個 getter function
在上面的範例中會有三個 getter function
,nameGet
, ageGet
, jobGet
他們會取得 person
的值並分別回傳 string
, int
, string
1 | [@bs.deriving abstract] |
至於改值則是
1 | [@bs.deriving abstract] |
note: 要記得將需要修改的參數前面加上 mutable
Object Methods
可以附加任何function
在類型上(任何類型的 record 不僅止於 @bs.deriving abtract
)
可以參閱 Object Method
這部分之後會再討埨
可變性
Test.re
1 | [@bs.deriving abstract] |
Test.rei
1 | [@bs.deriving abstract] |
Object2
如果上述的 Object 並不符合您的需求
也有另外一種方式可以綁定 Javascript Object
有幾個前提
- 你不想要預先宣告
type
- 你希望你的 Object 是有結構性的
Ex: 你的類型希望可以接受所有含有 age
這個參數的物件,而不是只有特定參數的物件
陷阱
note: 不能使用普通的 Reason/OCaml 的物件類型,如下
1 | type person = { |
你仍然可以宣告這個類型
但是無法編譯成功
因為 Reason/OCaml
的對象工作方式是不一樣的
解決方案
BuckleScript 利用 Js.t
來做包裝類型
以便控制和追蹤可以編譯成 Javascript 的對象子集合
1 | type person = Js.t({ |
從現在開始 BuckleScript 都會以 Js.t
來消除跟 一般物件 和 Javascript 物件的歧義
因為 Reason 有包覆一層語法糖 會將 Js.t({. name: string})
轉為 {. "name": string}
訪問 與 修改
取值
要取得值的話方法為 ##
範例如下
1 | type person = Js.t({ |
明天再來談談 Some
和 Option
的問題