文档 / 语言手册 / 绑定到 JS 对象
Edit

绑定到 JS 对象

JavaScript 中的对象有下面这些用例:

  • 作为数据存储,类似其他语言(比如 Rescript 和 C 语言)的“记录”或者“结构体”

  • 作为哈希表

  • 作为类

  • 作为输入或输出的模块

ReScript 清楚地区分这四种不同用途的 JS 对象的绑定方式。本章描述前三种情况。对 JS 模块对象的绑定会在从 JS 导入/导出到 JS中说明。

绑定到类似“记录”的 JS 对象

使用 ReScript 记录进行绑定

如果你的 JavaScript 对象有固定的字段,那么它在概念上就像一个 ReScript 记录。因为 ReScript 记录编译成干净的 JavaScript 对象,所以你可以将 JS 对象的类型标注为 ReScript 的记录!

ReScriptJS Output
type person = {
  name: string,
  friends: array<string>,
  age: int,
}

@module("MySchool") external john: person = "john"

let johnName = john.name

external 的相关文档在这里@module 的相关文档在这里

如果你想或者需要在 ReScript 端和 JavaScript 端使用不同的字段名,你可以用 @as 装饰器:

ReScriptJS Output
type action = {
  @as("type") type_: string
}

let action = {type_: "ADD_USER"}

这用于映射到无法在 ReScript 中表达的 JavaScript 属性名称(例如 ReScript 关键字)。

也可以通过将索引传递给 @as 装饰器来将 ReScript 记录映射到 JavaScript 数组:

ReScriptJS Output
type t = {
  @as("0") foo: int,
  @as("1") bar: string,
}

let value = {foo: 7, bar: "baz"}

使用 ReScript 对象进行绑定

除此之外,你也可以使用 ReScript 对象 去对 JS 对象进行建模:

ReScriptJS Output
type person = {
  "name": string,
  "friends": array<string>,
  "age": int,
}

@module("MySchool") external john: person = "john"

let johnName = john["name"]

使用特殊的 Getter 和 Setter 属性进行绑定

除此之外,你还可以使用 @get@set 去绑定 JS 对象的独立字段:

ReScriptJS Output
type textarea
@set external setName: (textarea, string) => unit = "name"
@get external getName: textarea => string = "name"

你也可以使用 @get_index@set_index 去访问动态属性或者索引:

ReScriptJS Output
type t
@new external create: int => t = "Int32Array"
@get_index external get: (t, int) => int = ""
@set_index external set: (t, int, int) => unit = ""

let i32arr = create(3)
i32arr->set(0, 42)
Js.log(i32arr->get(0))

绑定到类似哈希表的 JS 对象

如果你的 JavaScript 对象:

  • 可能会增加或者删除键

  • 只包含同类型的值

那么它不是真正意义上的对象,而是一个哈希表。我们可以使用 Js.Dict,它包含 getset 等操作并且仍然可以干净地编译为 JavaScript 对象。

绑定到作为类的 JS 对象

使用 @new 来模拟 new Date()

ReScriptJS Output
type t
@new external createDate: unit => t = "Date"

let date = createDate()

如果你要导入的 JS 模块本身是一个类,你可以将 newmodule 串联使用:

ReScriptJS Output
type t
@new @module external book: unit => t = "Book"
let myBook = book()