import
Оголошення статичного імпорту import
застосовуються для імпорту незмінних живих прив'язок, які, своєю чергою, експортуються іншим модулем. Імпортовані прив'язки називаються живими, оскільки вони оновлюються модулем, який їх експортує, проте їм не можуть бути присвоєні значення в модулі, що їх імпортує.
Для того, аби отримати змогу вжити оголошення import
у файлі з вихідним кодом, цей файл повинен бути інтерпретований середовищем виконання як модуль. В HTML цього можна досягти шляхом додавання type="module"
до тега <script>
. Модулі автоматично інтерпретуються в суворому режимі.
Також існує подібний до функції динамічний import()
, який не вимагає наявності атрибута type="module"
на скриптах.
Синтаксис
import defaultExport from "module-name";
import * as name from "module-name";
import { export1 } from "module-name";
import { export1 as alias1 } from "module-name";
import { default as alias } from "module-name";
import { export1, export2 } from "module-name";
import { export1, export2 as alias2, /* … */ } from "module-name";
import { "string name" as alias } from "module-name";
import defaultExport, { export1, /* … */ } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";
defaultExport
Назва, що вказує на усталений експорт із модуля. Повинна бути дійсним ідентифікатором JavaScript.
module-name
Модуль, з якого відбувається імпорт. Обчислення вказівника залежить від середовища. Часто це відносний чи абсолютний URL до файлу
.js
, що містить модуль. В середовищі Node імпорти без розширення часто вказують на пакунки уnode_modules
. Деякі пакувальні програми можуть допускати імпортування файлів без розширення — краще перевіряти налаштування середовища. Дозволяються лише рядки, виділені одинарними чи подвійними лапками.name
Назва об'єкта модуля, яку під час звертання до імпортів буде вжито як свого роду простір імен. Повинна бути дійсним ідентифікатором JavaScript.
exportN
Назви експортованих значень до імпорту. Така назва може бути як ідентифікатором, так і рядковим літералом — залежить від того, що саме модуль
module-name
оголосив до експорту. Якщо це рядковий літерал — йому слід призначити псевдонім, який уже буде дійсним ідентифікатором.aliasN
Псевдонім, що вказує на іменовані імпорти. Має бути дійсним ідентифікатором JavaScript.
Опис
Оголошення import
можуть знаходитися лише всередині модулів, і лише на найвищому рівні (тобто не всередині блоків, функцій тощо). Якщо оголошення import
зустрічається у немодульному контексті (як от у скриптових файлах, eval
, new Function
, які після розбору мають оформитися у "скрипт" чи "функцію") — викидається помилка SyntaxError
. Аби завантажити модуль у немодульному контексті — слід використовувати динамічний імпорт.
Оголошення import
сконструйовані таким чином, щоб бути синтаксично жорсткими (зокрема: допускаються лише літеральні рядкові вказівники, і лише на верхньому рівні — адже всі прив'язки є ідентифікаторами). Це дає можливість статично аналізувати модулі та синхронно їх компонувати, іще до їхнього виконання. Це — ключова особливість, необхідна аби зробити модулі асинхронними за природою, що дає змогу працювати функціональності штибу await
верхнього рівня.
Існує чотири форми оголошень import
:
- Іменований імпорт:
import { export1, export2 } from "module-name";
- Усталений імпорт:
import defaultExport from "module-name";
- Імпорт простору імен:
import * as name from "module-name";
- Імпорт заради побічних ефектів:
import "module-name";
Нижче наведено приклади для пояснення синтаксису.
Іменований імпорт
Нехай дано певне значення під назвою myExport
, експортоване з модуля my-module
або явно за допомогою інструкції export
, або неявно – як export * from "another.js"
. Такий код додасть значення myExport
у поточну область.
import { myExport } from "/modules/my-module.js";
З одного й того ж модуля можна імпортувати декілька імен.
import { foo, bar } from "/modules/my-module.js";
Можна перейменувати експорт під час імпортування його значення. Наприклад, цей код додає значення shortName
у поточну область видимості.
import { reallyReallyLongModuleExportName as shortName } from "/modules/my-module.js";
Модуль також може експортувати рядковий літерал, який не є дійсним ідентифікатором. В цьому випадку знадобиться звертатися до нього за псевдонімом, аби мати змогу користуватися ним у поточному модулі.
// /modules/my-module.js
const a = 1;
export { a as "a-b" };
import { "a-b" as a } from "/modules/my-module.js";
Примітка: Інструкція
import { x, y } from "mod"
не є еквівалентною доimport defaultExport from "mod"
і потім деструктуруванняx
таy
ізdefaultExport
. Усталений та іменований імпорт — це різні синтаксичні конструкції модулів JavaScript.
Усталений імпорт
Усталений експорт слід імпортувати за допомогою відповідного йому синтаксису усталеного імпорту. Найпростіший варіант безпосередньо імпортує усталене значення:
import myDefault from "/modules/my-module.js";
Оскільки усталений експорт не вказує імені явно, можна призначити ідентифікаторові будь-яке ім'я, за бажанням.
Також можливо вказувати усталений імпорт разом з імпортом простору імен чи іменованими імпортами. Проте в таких випадках усталений імпорт слід вказувати першим. Наприклад:
import myDefault, * as myModule from "/modules/my-module.js";
// myModule.default та myDefault вказують на одну прив'язку
...або ж:
import myDefault, { foo, bar } from "/modules/my-module.js";
Імпортування значення, яке називається default
, має ефект, ідентичний усталеному імпортові. Йому необхідно призначати псевдонім, оскільки default
— це зарезервоване слово.
import { default as myDefault } from "/modules/my-module.js";
Імпорт простору імен
Наступний код вставляє myModule
, який містить всі значення, експортовані з модуля /modules/my-module.js
, у поточну область.
import * as myModule from "/modules/my-module.js";
В цьому випадку myModule
є об'єктом простору імен, який вміщує всі експортовані значення як звичайні властивості. Наприклад, якщо імпортований вище модуль містить експорт doAllTheAmazingThings()
, його можна було б викликати таким чином:
myModule.doAllTheAmazingThings();
Значення myModule
— це запечатаний об'єкт, чиїм прототипом є null
. Усталений експорт доступний за ключем, що зветься default
. Більше інформації про це – в розділі об'єкта простору імен модуля.
Примітка: JavaScript не підтримує довільні імпорти, як от
import * from "module-name"
, через високу ймовірність конфліктів імен.
Імпортування модуля лише заради його побічних ефектів
Імпорт цілого модуля лише заради його побічних ефектів, без імпортування чогось конкретного. Це запускає глобальний код модуля, проте не імпортує жодних значень.
import "/modules/my-module.js";
Такий підхід часто використовується для поліфілів, які модифікують глобальні змінні.
Приклади
Стандартний імпорт
У цьому прикладі створюється модуль, придатний для повторного використання, який експортує функцію для отримання всіх простих чисел всередині вказаного діапазону.
// getPrimes.js
/**
* Повертає список простих чисел, що менші за передане `max`.
*/
export function getPrimes(max) {
const isPrime = Array.from({ length: max }, () => true);
isPrime[0] = isPrime[1] = false;
isPrime[2] = true;
for (let i = 2; i * i < max; i++) {
if (isPrime[i]) {
for (let j = i ** 2; j < max; j += i) {
isPrime[j] = false;
}
}
}
return [...isPrime.entries()]
.filter(([, isPrime]) => isPrime)
.map(([number]) => number);
}
import { getPrimes } from "/modules/getPrimes.js";
console.log(getPrimes(10)); // [2, 3, 5, 7]
Імпортовані значення можуть модифікуватися лише експортером
Імпортований ідентифікатор є живою прив'язкою, оскільки модуль, що експортує його, може також присвоїти йому нове значення, і тоді імпортоване значення зміниться. Проте модуль, що імпортує його, присвоїти йому нове значення не може. Попри це, будь-який модуль, що користується імпортованим об'єктом, може змінювати його, і таке змінене значення буде спостерігатися в усіх модулях, що імпортують той самий об'єкт.
Крім цього, нове значення можна спостерігати крізь об'єкт простору імен модуля.
// my-module.js
export let myValue = 1;
setTimeout(() => {
myValue = 2;
}, 500);
// main.js
import { myValue } from "/modules/my-module.js";
import * as myModule from "/modules/my-module.js";
console.log(myValue); // 1
console.log(myModule.myValue); // 1
setTimeout(() => {
console.log(myValue); // 2; my-module оновив своє значення
console.log(myModule.myValue); // 2
myValue = 3; // TypeError: Assignment to constant variable.
// Приймаючий модуль може лише читати значення, проте не перезаписувати його.
}, 1000);
Специфікації
Специфікація |
---|
ECMAScript Language Specification (ECMAScript) # sec-imports |
ECMAScript Language Specification (ECMAScript) # sec-import-calls |
Сумісність із браузерами
desktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
import
|
Chrome Full support 61 | Edge Full support 16 | Firefox Full support 60 | Internet Explorer No support No | Opera Full support 48 | Safari Full support 10.1 | WebView Android Full support 61 | Chrome Android Full support 61 | Firefox for Android Full support 60 | Opera Android Full support 45 | Safari on iOS Full support 10.3 | Samsung Internet Full support 8.0 | Deno Full support 1.0 | Node.js Full support 13.2.0 |
Dynamic import
|
Chrome Full support 63 | Edge Full support 79 | Firefox Full support 67 | Internet Explorer No support No | Opera Full support 50 | Safari Full support 11.1 | WebView Android Full support 63 | Chrome Android Full support 63 | Firefox for Android Full support 67 | Opera Android Full support 46 | Safari on iOS Full support 11.3 | Samsung Internet Full support 8.0 | Deno Full support 1.0 | Node.js Full support 13.2.0 |
Available in workers
|
Chrome Full support 80 | Edge Full support 80 | Firefox No support No | Internet Explorer No support No | Opera No support No | Safari Full support 15 | WebView Android Full support 80 | Chrome Android Full support 80 | Firefox for Android No support No | Opera Android No support No | Safari on iOS Full support 15 | Samsung Internet Full support 13.0 | Deno Full support 1.0 | Node.js No support No |
Дивіться також
export
- Динамічні імпорти
import.meta
- Лімін Зу, Браян Терлсон і команда Microsoft Edge: Попередній огляд модулів ES6 та інше, з ES2015, ES2016 і далі (англ.)
- Допис із хаками від Джейсона Орендорффа: Поглиблено про ES6: Модулі (англ.)
- Допис із хаками від Лін Кларк: Модулі ES: поглиблено і з малюнками (англ.)
- Книга Акселя Раушмаєра: "Дослідження JS: Модулі" (англ.)
- Сучасний підручник з JavaScript (uk.javascript.info): Експорт та імпорт