As importações do módulo ES6 são içadas?

Eu sei que na nova syntax do módulo ES6, o mecanismo JavaScript não terá que avaliar o código para saber sobre todas as importações / exportações, ele só irá analisá- lo e “saber” o que carregar.

Isso soa como içar. Os módulos do ES6 são içados? E se assim for, todos eles serão carregados antes de executar o código?

Este código é possível?

import myFunc1 from 'externalModule1'; myFunc2(); if (Math.random()>0.5) { import myFunc2 from 'externalModule2'; } 

Será um SyntaxError . De acordo com esta parte da especificação :

 Module : ModuleBody ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem 

Isso significa que o módulo pode conter apenas ImportDeclaration , ExportDeclaration ou StatementListItem . De acordo com este StatementListItem não pôde conter ImportDeclaration nem ExportDeclaration .

 import myFunc1 from 'externalModule1'; 

é uma declaração de importação, enquanto:

 if (Math.random()>0.5) { import myFunc2 from 'externalModule2'; } 

é uma afirmação. Então, seu código resultará em um erro de syntax.

E quanto a “todos eles serão carregados antes de executar o código?”. Esta parte da especificação contém a próxima frase:

NOTA: Antes de instanciar um módulo, todos os módulos solicitados devem estar disponíveis.

Então sim. Eles serão todos carregados antes de executar o código .

Depois de fazer mais pesquisas, descobri:

  • As importações são içadas! de acordo com as especificações do ModuleDeclarationInstantiation
  • TODOS os módulos dependentes serão carregados antes de executar qualquer código.

Este código não terá erros e funcionará:

 localFunc(); import {myFunc1} from 'mymodule'; function localFunc() { // localFunc is hoisted myFunc1(); } 

A especificação ES6 está sujeita a alterações, mas este rascunho é explícito:

A resolução da variável estática e a passagem de binding verificam conflitos em nomes de variables ​​importados. Se houver um conflito entre dois nomes importados ou um nome importado e outra binding local, será um erro de tempo de compilation.

E tentar importar em tempo de execução é uma ideia duvidosa, não apenas no ES6. Também do rascunho:

A compilation resolve e valida todas as definições e referências de variables. A binding também acontece em tempo de compilation; A vinculação resolve e valida todas as importações e exportações do módulo.

Você pode ver que a implementação do ES6 da Babel não está muito feliz com isso.