Інструкції експорту і імпорту, які ми розглядали в попередньому розділі, називаються “статичними”. Синтаксис у них дуже простий і строгий.
По-перше, ми не можемо динамічно задавати ніякі з параметрів import.
Шлях до модуля має бути рядком і не може бути викликом функції. Ось так працювати не буде:
import ... from getModuleName(); // Помилка, має бути рядок По-друге, ми не можемо робити імпорт залежно від умов або в процесі виконання:
if(...) { import ...; // Помилка, заборонено } { import ...; // Помилка, ми не можемо ставити імпорт у блок } Усе це результат того, що мета директив import/export – задати кістяк структури коду. Завдяки ним вона може бути проаналізована, модулі можуть бути зібрані в один файл спеціальними інструментами, а невживані експорти видалені. Це можливо тільки завдяки тому, що все статично.
Але як ми можемо імпортувати модуль динамічно, за запитом?
Вираз import()
Вираз import(module) завантажує модуль і повертає проміс, результатом якого стає об’єкт модуля, що містить усі його експорти.
Ми можемо використати його у будь-якому місці коду, наприклад, так:
let modulePath = prompt("Який модуль завантажити?"); import(modulePath) .then(obj => <об’єкт модуля>) .catch(err => <помилка завантаження, наприклад якщо немає такого модуля>) Чи якщо усередині асинхронної функції, то можна використати let module = await import(modulePath).
Наприклад, якщо у нас є такий модуль say.js:
// 📁 say.js export function hi() { alert(`Привіт`); } export function bye() { alert(`Бувай`); } …То динамічний імпорт може виглядати так:
let {hi, bye} = await import('./say.js'); hi(); bye(); А якщо в say.js вказаний типовий експорт:
// 📁 say.js export default function() { alert("Модуль завантажився (export default)!"); } …То для доступу до нього нам слід узяти властивість default об’єкту модуля:
let obj = await import('./say.js'); let say = obj.default; // або одним рядком: let {default: say} = await import('./say.js'); say(); Ось повний приклад:
export function hi() { alert(`Привіт`); } export function bye() { alert(`Бувай`); } export default function() { alert("Модуль завантажений (export default)!"); }<!doctype html> <script> async function load() { let say = await import('./say.js'); say.hi(); // Привіт! say.bye(); // Бувай! say.default(); // Модуль завантажений (export default)! } </script> <button onclick="load()">Натисни мене</button>Динамічний імпорт працює в звичайних скриптах, він не вимагає вказівки script type="module".
Хоча import() і виглядає схожим на виклик функції, насправді це спеціальний синтаксис, так само, як, наприклад, super().
Тому ми не можемо скопіювати import в іншу змінну або викликати за допомогою .call/apply. Це не функція.
Коментарі
<code>, для кількох рядків – обгорніть їх тегом<pre>, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)