0

In implementing the Python module mechanism on top of ES6 modules for the Transcrypt Python to JavaScript compiler, I am faced with the following problem:

There are a large number of standard functions imported from the Python runtime module, like e.g. the Python input function (implemented in JS), which can be made available using named imports (since they shouldn't have to be prefixed with anything in the user code, so input rather than __runtime__.input, to be consistent with Python).

In Python it's allowed to rebind named imports. So I define another function input, which will override the one from the runtime. But if I do so in JS, I get an error:

Identifier 'input' has already been declared

It seems that all imported names are regarded as JS consts, so non-rebindable according to this article. I can think of several clever workarounds, like importing under an alias and then assigning to a module global var rather than const, but like to keep things simple, so my question is:

  • Am I right that JS named imports are consts, so non-rebindable (and if so, just curious, anyone knows WHY)? Where can I find details on this?
  • Is there a simple way to circumvent that and still put them in the global namespace of the importing module, but override them at will?
4

1 回答 1

2

根据语言规范,导入的绑定是不可变的绑定,因此无法更改。由于 ES6 模块的工作方式,标识符在模块被解析时被保留:与 Python 不同,导入不是在执行时包含的语句;相反,所有模块的导入基本上都是在早期编译期间收集的,然后在模块开始执行之前解析。

这使得 ES6 模块有点不适合作为 Python 导入系统的实现。

作为一般方法,为避免丢失这些名称,您可以简单地为导入的绑定赋予不同的名称。例如 anfrom foo import bar, baz可以编译为以下内容:

import { bar as _foo__bar, baz as _foo__baz } from 'foo';
let bar = _foo__bar;
let baz = _foo__baz;

这只会保留一些特殊名称,同时保持barbaz标识符可变。

另一种可能也可以帮助您解决可能的导入语义差异的方法是简单地创建一个闭包:

import { bar, baz } from 'foo';

(function (bar, baz) {
    // …

})(bar, baz);

甚至在两者之间添加一些其他查找机制。


顺便提一句。Pythonimport与 Node 非常相似require,因此可能值得研究所有使 Node 的模块系统在浏览器中工作的解决方案。

于 2018-04-05T19:07:09.887 回答