ES6 назвал импорт вводит const?
При реализации механизма модулей Python поверх модулей ES6 для компилятора Transcrypt Python to JavaScript я столкнулся со следующей проблемой:
Существует большое количество стандартных функций, импортированных из модуля времени выполнения Python, например, Python. input
функция (реализована в JS), которая может быть сделана доступной с помощью именованного импорта (так как им не нужно добавлять префикс к чему-либо в коде пользователя, поэтому input
скорее, чем __runtime__.input
, чтобы соответствовать Python).
В Python разрешено повторное связывание именованного импорта. Поэтому я определяю другую функцию input
, который переопределит тот из среды выполнения. Но если я делаю это в JS, я получаю ошибку:
Идентификатор input уже объявлен
Кажется, что все импортированные имена рассматриваются как JS-константы, поэтому не подлежат повторному связыванию в соответствии с этой статьей. Я могу придумать несколько хитрых обходных путей, таких как импорт под псевдонимом и последующее присвоение модулю глобального var, а не const, но мне нравится, чтобы все было просто, поэтому мой вопрос:
- Прав ли я, что именованные импорты JS являются консистентными, поэтому не подлежат повторному связыванию (и если да, то просто любопытно, кто-нибудь знает ПОЧЕМУ)? Где я могу найти подробности об этом?
- Есть ли простой способ обойти это и все же поместить их в глобальное пространство имен импортирующего модуля, но переопределить их по желанию?
1 ответ
В соответствии со спецификацией языка импортированные привязки являются неизменными, поэтому их нельзя изменить. Идентификаторы зарезервированы, когда модуль анализируется из-за того, как работают модули 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);
Или даже добавить какой-то другой механизм поиска между ними.
Btw. Питона import
очень похож на Node's require
так что, возможно, стоит рассмотреть все те решения, которые позволили модульной системе Node работать в браузере.