不同 ReasonML 外部声明的含义是什么?

What are the Implications of Different ReasonML External Declarations?

在下面的示例中,两个外部声明都实现了相同的功能,但 ReasonML 函数结构略有不同。

外部声明 style 是否会影响 ReasonML 函数结构之外的任何内容(例如性能)?此外,ReasonML 是否有 "suggested" 外部声明 "style"?

类型声明

type dom;
type element;

外部声明样式 1

[@bs.val] 
external dom: dom = "document";
[@bs.send.pipe : dom]
external get_by_id: string => element = "getElementById";

外部声明样式 2

[@bs.scope "document"] [@bs.val]
external by_id: string => element = "getElementById";

ReasonML 函数调用

let tag1 = dom |> get_by_id("main");
let tag2 = by_id("main")

从它们的使用方式来看,主要区别应该很明显。

let tag1 = dom |> get_by_id("main"); // has two parts
let tag2 = by_id("main") // has only one part

拥有两个部分意味着您可以将每个部分与其他部分互换,只要它们具有相同的类型签名即可。例如,我们可以用 dom(类型)的不同实例替换 dom(值):

[@bs.new]
external make_doc: unit => dom = "Document";

let tag3 = make_doc() |> get_by_id("main");

然而,这还有更微妙的含义。有两个部分意味着您可以在不同的上下文中评估这些部分。这并不容易说明,但考虑这个人为的例子:

[@bs.val] 
external dom: dom = "document";

let dom1 = dom;

[%%raw {|var document = null|}];

let dom2 = dom;

let tag1 = dom1 |> get_by_id("main");
let tag2 = dom2 |> get_by_id("main");
let tag3 = by_id("main")
这里的

dom1dom2指的是不同的值。使用 dom1 将按预期工作,而使用 dom2 将崩溃。 by_id.

那么你应该使用哪个?嗯,这取决于你需要什么。如果您将始终使用当前范围内的 document,请使用 bs.scope,因为这样更方便。如果你不这样做,或者你想使用具有多个不同值的相同函数,请使用 @bs.send/@bs.send.pipe.