Výkazy exportu a importu, které jsme probrali v předchozích kapitolách, se nazývají „statické“. Syntaxe je velmi jednoduchá a přísná.
Za prvé, nemůžeme dynamicky generovat žádné parametry import
.
Cesta modulu musí být primitivní řetězec, nemůže to být volání funkce. Toto nebude fungovat:
import ... from getModuleName(); // Error, only from "string" is allowed
Za druhé, nemůžeme importovat podmíněně nebo za běhu:
if(...) {
import ...; // Error, not allowed!
}
{
import ...; // Error, we can't put import in any block
}
To proto, že import
/export
Cílem je poskytnout páteř pro strukturu kódu. To je dobrá věc, protože strukturu kódu lze analyzovat, moduly lze shromáždit a seskupit do jednoho souboru pomocí speciálních nástrojů, nepoužívané exporty lze odstranit („stromově otřesené“). To je možné pouze proto, že struktura importů/exportů je jednoduchá a pevná.
Jak ale můžeme modul importovat dynamicky, na vyžádání?
Výraz import()
import(module)
výraz načte modul a vrátí příslib, který se převede na objekt modulu, který obsahuje všechny jeho exporty. Lze jej volat z libovolného místa v kódu.
Můžeme jej použít dynamicky na libovolném místě kódu, například:
let modulePath = prompt("Which module to load?");
import(modulePath)
.then(obj => <module object>)
.catch(err => <loading error, e.g. if no such module>)
Nebo bychom mohli použít let module = await import(modulePath)
pokud je součástí asynchronní funkce.
Například, pokud máme následující modul say.js
:
// 📁 say.js
export function hi() {
alert(`Hello`);
}
export function bye() {
alert(`Bye`);
}
…Pak dynamický import může vypadat takto:
let {hi, bye} = await import('./say.js');
hi();
bye();
Nebo, pokud say.js
má výchozí export:
// 📁 say.js
export default function() {
alert("Module loaded (export default)!");
}
…Poté, abychom k němu měli přístup, můžeme použít default
vlastnost objektu modulu:
let obj = await import('./say.js');
let say = obj.default;
// or, in one line: let {default: say} = await import('./say.js');
say();
Zde je úplný příklad:
Resultsay.jsindex.htmlexport function hi() {
alert(`Hello`);
}
export function bye() {
alert(`Bye`);
}
export default function() {
alert("Module loaded (export default)!");
}
<!doctype html>
<script>
async function load() {
let say = await import('./say.js');
say.hi(); // Hello!
say.bye(); // Bye!
say.default(); // Module loaded (export default)!
}
</script>
<button onclick="load()">Click me</button>
Poznámka:
Dynamické importy fungují v běžných skriptech, nevyžadují script type="module"
.
Ačkoli import()
vypadá jako volání funkce, je to speciální syntaxe, která náhodou používá závorky (podobně jako super()
).
Nemůžeme tedy zkopírovat import
na proměnnou nebo použijte call/apply
s tím. Není to funkce.