import
Baseline Широко доступно
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с мая 2018 года.
Статический оператор import используется для импорта неизменяемых "live" привязок (bindings), которые экспортируются другим модулем. Импортируемые привязки называются live bindings, потому что они обновляются модулем, который их экспортировал, но не могут быть переназначены импортирующим модулем.
Чтобы использовать оператор 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-адреса, относительные к URL текущего модуля (см.
import.meta.url). Node.js, бандлеры и другие среды, не являющиеся браузерными, часто расширяют эти правила, поэтому вам следует обратиться к их документации, чтобы понять точные правила. В разделе разрешение спецификаторов модулей также есть дополнительная информация. -
name - Имя объекта модуля, которое будет использоваться как своего рода пространство имен при обращении к импортам. Должно быть допустимым идентификатором JavaScript.
-
exportN - Имя экспортируемых элементов. Имя может быть как идентификатором, так и строковым литералом, в зависимости от того, что объявляет
module-nameдля экспорта. Если это строковый литерал, он должен быть псевдонимом (aliased) допустимого идентификатора. -
aliasN - Имена, которые будут ссылаться на именованные импорты. Должны быть допустимыми идентификаторами JavaScript.
За "module-name" может следовать набор атрибутов импорта, начиная с ключевого слова with.
Описание
import декларации могут присутствовать только в модулях и только на верхнем уровне (т.е. не внутри блоков, функций и т.д.). Если декларация import встречается в контекстах, не являющихся модулями (например, теги <script> без type="module", eval, new Function, которые все имеют "script" или "function body" в качестве целей парсинга), будет выброшено SyntaxError. Для загрузки модулей в контекстах, не являющихся модулями, вместо этого используйте синтаксис динамического импорта.
Все импортированные привязки не могут находиться в той же области видимости, что и любые другие объявления, включая let, const, class, function, var и декларации import.
import декларации разработаны так, чтобы быть синтаксически жесткими (например, только строковые литералы-спецификаторы, только разрешенные на верхнем уровне, все привязки должны быть идентификаторами), что позволяет статически анализировать и связывать модули перед их вычислением. Это ключ к асинхронной природе модулей, обеспечивающий такие возможности, как top-level await.
Ключевое слово import может сопровождаться "модификатором фазы", который останавливает процесс импорта модуля на определенной фазе:
Каждый из этих синтаксисов считается отдельным типом декларации.
Формы деклараций import
Существует четыре формы деклараций 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 * from "another.js", либо явно с помощью оператора export, это вставляет 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 and myDefault point to the same binding
или
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 нет операторов импорта по wildcard, таких как import * from "module-name", из-за высокой вероятности конфликтов имен.
Импорт модуля только для побочных эффектов
Импортируйте весь модуль только для побочных эффектов, не импортируя ничего. Это запускает глобальный код модуля, но фактически не импортирует никаких значений.
import "/modules/my-module.js";
Это часто используется для полифиллов, которые мутируют глобальные переменные.
Поднятие (Hoisting)
Декларации `import` поднимаются. В данном случае это означает, что идентификаторы, введенные импортами, доступны во всей области видимости модуля, и их побочные эффекты производятся до выполнения остального кода модуля.
myModule.doAllTheAmazingThings(); // myModule.doAllTheAmazingThings is imported by the next line import * as myModule from "/modules/my-module.js";
Разрешение спецификаторов модулей
Спецификация ECMAScript не определяет, как разрешаются спецификаторы модулей, и оставляет это на усмотрение хост-среды (например, браузеров, Node.js, Deno). Поведение браузеров определяется спецификацией HTML, и это стало де-факто стандартом для всех сред.
Существует три типа спецификаторов, широко признанных и реализованных в спецификации HTML, Node.js и многих других:
-
Относительные спецификаторы, которые начинаются с
/,./или../, и разрешаются относительно URL текущего модуля. - Абсолютные спецификаторы, которые являются URL-адресами, поддающимися разбору, и разрешаются как есть.
- Голые спецификаторы, которые не относятся к первым двум категориям.
Наиболее заметным предостережением для относительных спецификаторов, особенно для тех, кто знаком с соглашениями CommonJS, является то, что браузеры запрещают одному спецификатору неявно разрешаться в несколько потенциальных кандидатов. В CommonJS, если у вас есть main.js и utils/index.js, то все следующие примеры импортируют "экспорт по умолчанию" из utils/index.js:
// main.js
const utils = require("./utils"); // Omit the "index.js" file name
const utils = require("./utils/index"); // Omit only the ".js" extension
const utils = require("./utils/index.js"); // The most explicit form
В вебе это дорого, потому что если вы напишете import x from "./utils", браузеру придется отправлять запросы на utils, utils/index.js, utils.js и потенциально многие другие URL, пока он не найдет импортируемый модуль. Поэтому в спецификации HTML спецификатор по умолчанию может быть только URL, разрешенным относительно URL текущего модуля. Вы не можете опустить расширение файла или имя файла index.js. Это поведение унаследовано реализацией ESM в Node.js, но не является частью спецификации ECMAScript.
Обратите внимание, что это не означает, что import x from "./utils" никогда не работает в вебе. Браузер все равно отправляет запрос на этот URL, и если сервер может ответить правильным содержимым, импорт будет успешным. Это требует от сервера реализации некоторой пользовательской логики разрешения, потому что обычно запросы без расширения воспринимаются как запросы на HTML-файлы.
Абсолютные спецификаторы могут быть любым URL, который разрешается в импортируемый исходный код. Наиболее примечательные:
- URL HTTP всегда поддерживаются в вебе, поскольку большинство скриптов уже имеют URL HTTP. Они нативно поддерживаются Deno (который изначально основывал всю свою систему модулей на URL HTTP), но имеют лишь экспериментальную поддержку в Node.js через пользовательские загрузчики HTTPS.
-
URL
file:поддерживаются многими средами выполнения, не являющимися браузерными, такими как Node.js, поскольку скрипты там уже имеют URLfile:, но они не поддерживаются браузерами по соображениям безопасности. -
URL данных поддерживаются многими средами выполнения, включая браузеры, Node.js, Deno и т.д. Они полезны для встраивания небольших модулей непосредственно в исходный код. Поддерживаемые типы MIME — это те, которые обозначают импортируемый исходный код, такие как
text/javascriptдля JavaScript,application/jsonдля JSON-модулей,application/wasmдля модулей WebAssembly и т.д. (они все еще могут требовать атрибуты импорта.)// HTTP URLs import x from "https://example.com/x.js"; // Data URLs import x from "data:text/javascript,export default 42;"; // Data URLs for JSON modules import x from 'data:application/json,{"foo":42}' with { type: "json" };text/javascriptURL данных по-прежнему интерпретируются как модули, но они не могут использовать относительные импорты, поскольку схема URLdata:не является иерархической. То есть,import x from "data:text/javascript,import y from './y.js';"вызовет ошибку, поскольку относительный спецификатор'./y.js'не может быть разрешен. -
URL
node:разрешаются во встроенные модули Node.js. Они поддерживаются Node.js и другими средами выполнения, которые претендуют на совместимость с Node.js, такими как Bun.
Голые спецификаторы, популяризированные CommonJS, разрешаются в каталоге node_modules. Например, если у вас есть import x from "foo", среда выполнения будет искать пакет foo в любом каталоге node_modules в родительских каталогах текущего модуля. Такое поведение может быть воспроизведено в браузерах с использованием import maps, которые также позволяют настраивать разрешение другими способами.
Алгоритм разрешения модулей также может быть выполнен программно с использованием функции import.meta.resolve, определенной в спецификации HTML.
Примеры
Стандартный импорт
В этом примере мы создаем повторно используемый модуль, который экспортирует функцию для получения всех простых чисел в заданном диапазоне.
// getPrimes.js
/**
* Returns a list of prime numbers that are smaller than `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]
Импортированные значения могут быть изменены только экспортером
Импортируемый идентификатор является live binding, поскольку модуль, экспортирующий его, может переназначить его, и импортированное значение изменится. Однако модуль, импортирующий его, не может его переназначить. Тем не менее, любой модуль, имеющий объект экспорта, может мутировать объект, и измененное значение может наблюдаться всеми другими модулями, импортирующими то же значение.
Вы также можете наблюдать новое значение через объект пространства имен модуля.
// 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 has updated its value
console.log(myModule.myValue); // 2
myValue = 3; // TypeError: Assignment to constant variable.
// The importing module can only read the value but can't re-assign it.
}, 1000);
Импорт не-JavaScript модулей
Не-JavaScript модули также могут быть импортированы с использованием оператора import, но их типы должны быть явно объявлены с использованием атрибутов импорта. Например, чтобы импортировать JSON-модуль, вам нужно указать атрибут type: "json".
import data from "./data.json" with { type: "json" };
Спецификации
| Спецификация |
|---|
| ECMAScript® 2027 Language Specification # sec-imports |
Совместимость с браузерами
| Настольные ПК | Мобильные | Сервер | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
import |
61 |
16 |
60 |
48 |
10.1 |
61 |
60 |
45 |
10.3 |
8.0 |
61 |
10.3 |
1.0.0 |
1.0 |
13.2.0Модули должны иметь имя файла, оканчивающееся на.mjs, или ближайший родительский файл package.json должен содержать "type": "module". См. документацию по модулям ECMAScript Node.js для получения более подробной информации.12.17.0–13.0.0Модули должны иметь имя файла, оканчивающееся на.mjs, или ближайший родительский файл package.json должен содержать "type": "module". См. документацию по модулям ECMAScript Node.js для получения более подробной информации. |
arbitrary_module_namespace_identifier_names |
88 |
88 |
87 |
74 |
14.1 |
88 |
87 |
63 |
14.5 |
15.0 |
88 |
14.5 |
1.0.15 |
1.6 |
16.0.0 |
defer |
Нет |
Нет |
Нет |
Нет |
preview |
Нет |
Нет |
Нет |
Нет |
Нет |
Нет |
Нет |
? |
? |
? |
import_assertions |
91–126 |
91–126 |
Нет |
Нет |
Нет |
91–126 |
Нет |
Нет |
Нет |
16.0–28.0 |
91–126 |
Нет |
1.0.0 |
1.17 |
16.14.0–22.0.0 |
import_attributes |
123 |
123 |
138 |
109 |
17.2 |
123 |
138 |
82 |
17.2 |
27.0 |
123 |
17.2 |
1.0.0 |
1.37 |
20.10.0
18.20.0–19.0.0
|
import_source |
Нет |
Нет |
153 |
Нет |
Нет |
Нет |
153 |
Нет |
Нет |
Нет |
Нет |
Нет |
Нет |
Нет |
Нет |
service_worker_support |
91 |
91 |
147 |
77 |
15 |
91 |
147 |
64 |
15 |
16.0 |
91 |
15 |
1.0.0 |
Нет |
Нет |
worker_support |
80 |
80 |
114 |
67 |
15 |
80 |
114 |
57 |
15 |
13.0 |
80 |
15 |
1.0.0 |
1.0 |
Нет |
worklet_support |
Нет |
Нет |
114 |
Нет |
Нет |
Нет |
114 |
Нет |
Нет |
Нет |
Нет |
Нет |
1.0.0 |
Нет |
Нет |
См. также
exportimport()import.meta- Атрибуты импорта
- Previewing ES6 Modules and more from ES2015, ES2016 and beyond на blogs.windows.com (2016)
- ES6 in Depth: Modules на hacks.mozilla.org (2015)
- ES modules: A cartoon deep-dive на hacks.mozilla.org (2018)
- Exploring JS, Ch.16: Modules от Dr. Axel Rauschmayer
- Экспорт и импорт на javascript.info
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import