在Transcrypt Python到JavaScript编译器的ES6模块之上实现Python模块机制时,我遇到了以下问题:
从Python运行时模块导入了大量标准函数,例如Python input
函数(在JS中实现),可以使用命名导入提供(因为它们不应该以用户代码中的任何内容为前缀,因此input
而不是__runtime__.input
{1}},与Python一致。)
在Python中,它允许重新绑定命名导入。所以我定义了另一个函数input
,它将覆盖运行时的函数。但如果我在JS中这样做,我会收到一个错误:
标识符'输入'已经宣布
似乎所有导入的名称都被视为JS consts,因此根据this article不可重新绑定。我可以想到几个聪明的解决方法,比如在别名下导入然后分配给模块全局变量而不是const,但是为了简单起见,所以我的问题是:
答案 0 :(得分:1)
作为per the language specification,导入的绑定是不可变绑定,因此无法更改它们。由于ES6模块的工作方式,模块被解析时保留标识符:与Python不同,导入不是在执行时包含的语句;相反,所有模块的导入基本上都是在早期编译期间收集的,然后在模块开始执行之前解决。
这使得ES6模块不适合作为Python导入系统的实现。
作为一般方法,为避免丢失这些名称,您只需为导入的绑定指定不同的名称即可。例如,可以将from foo import bar, baz
编译为以下内容:
import { bar as _foo__bar, baz as _foo__baz } from 'foo';
let bar = _foo__bar;
let baz = _foo__baz;
这样只保留一些特殊名称,同时保持bar
和baz
标识符可变。
另一种可能也有助于解决可能的导入语义差异的方法是简单地创建一个闭包:
import { bar, baz } from 'foo';
(function (bar, baz) {
// …
})(bar, baz);
甚至可以在其间添加一些其他查找机制。
顺便说一下。 Python的import
与Node的require
非常相似,因此可能值得研究使Node的模块系统在浏览器中工作的所有解决方案。