模块名称在绑定中隐藏了全局名称

时间:2019-02-21 09:20:59

标签: javascript binding ffi reason bucklescript

tl; dr::如何更改以下绑定以能够写Intl.DateTimeFormat.make()而不是Intl_.DateTimeFormat.make()

type dateTimeFormat;

[@bs.deriving abstract]
type formatOptions = {
  [@bs.optional]
  weekday: string,
  [@bs.optional]
  day: string,
  [@bs.optional]
  month: string,
};

module Intl_ {
    module DateTimeFormat {
      module Impl {
        type t;
      };

      [@bs.new] external make: unit => Impl.t = "Intl.DateTimeFormat";
      [@bs.send] external format: (Impl.t, Js.Date.t) => string = "";
    };
}

Intl_.DateTimeFormat.make()
  ->Intl_.DateTimeFormat.format(Js.Date.make())
  ->Js.log;

问题

没有下划线,它将编译为:

var Impl = /* module */[];

var DateTimeFormat = /* module */[/* Impl */Impl];

var Intl = /* module */[/* DateTimeFormat */DateTimeFormat];

console.log(new Intl.DateTimeFormat().format(new Date()));

exports.Intl = Intl;

问题在于var Intl = ...遮盖了全局Intl,从而破坏了new Intl.DateTimeFormat()

1 个答案:

答案 0 :(得分:1)

首先,我认为这是BuckleScript中的错误。这个问题是最近在issue #3268中提出的,并在this commit中得到部分解决,但是仍然保留了许多名称。您应该考虑将其提出来或在新一期中进行。

同时,您可以通过完全限定名称来解决此问题。 Intl实际上不是全局对象,而是附加到 the 全局对象,该对象在网页的上下文中为window。但是,由于JavaScript会在本地环境中找不到全局对象时在全局对象上查找名称,因此它看起来非常像全局名称。

因此,如果您将make更改为:

[@bs.new] external make: unit => Impl.t = "window.Intl.DateTimeFormat";

它应该可以正常工作。