aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/javascript/reference/statements/import/index.html
blob: d301e393270c8b92d4c3c1505dec8434d2be2a2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
---
title: import
slug: Web/JavaScript/Reference/Statements/import
tags:
  - ECMAScript 2015
  - ECMAScript6
  - JavaScript
  - import
  - Инструкция
  - Модули
  - динамический импорт
  - импорт
translation_of: Web/JavaScript/Reference/Statements/import
---
<div>{{jsSidebar("Statements")}}</div>

<p>Инструкция <strong>import</strong> используется для импорта ссылок на значения, экспортированные из внешнего модуля. Импортированные модули находятся в {{JSxRef ("Strict_mode", "строгом режиме")}} независимо от того, объявляете ли вы их как таковые или нет. Для работы инструкции во встроенных скриптах нужно прописать у тэга script <code>type="module"</code>.</p>

<p>Существует также function-like динамический <code>import()</code>, который не требует скриптов с типом "<code>module</code>".</p>

<p>Обратная совместимость может быть обеспечена с помощью атрибута <code>nomodule</code> тега <a href="/ru/docs/Web/HTML/Element/script">script</a>.</p>

<p>Динамический импорт полезен в ситуациях, когда вы хотите загрузить модуль условно или по требованию. Статическая форма предпочтительна для загрузки начальных зависимостей и может быть более полезна для инструментов статического анализа и <a href="/en-US/docs/Glossary/Tree_shaking">tree shaking</a>.</p>

<div class="note">
<p><strong>Внимание:</strong> На данный момент эта функциональность <a href="https://jakearchibald.com/2017/es-modules-in-browsers/">только начинает поддерживаться</a> браузерами. Полноценная реализация присутствует во многих транспайлерах, таких как TypeScript и <a href="http://babeljs.io/">Babel</a>, а также в сборщиках, например, в <a href="https://github.com/rollup/rollup">Rollup</a> и <a href="https://webpack.js.org/">Webpack</a>.</p>
</div>

<h2 id="Синтаксис">Синтаксис</h2>

<pre class="syntaxbox">import <em>defaultExport</em> from "<em>module-name</em>";
import * as <em>name</em> from "<em>module-name</em>";
import { <em>export </em>} from "<em>module-name</em>";
import { <em>export</em> as <em>alias </em>} from "<em>module-name</em>";
import { <em>export1 , export2</em> } from "<em>module-name</em>";
import { <em>export1 , export2</em> as <em>alias2</em> , <em>[…]</em> } from "<em>module-name</em>";
import <em>defaultExport</em>, { <em>export</em> [ , <em>[…]</em> ] } from "<em>module-name</em>";
import <em>defaultExport</em>, * as <em>name</em> from "<em>module-name</em>";
import "<em>module-name</em>";
import("/module-name.js").then(module =&gt; {…}) // Динамический импорт
</pre>

<dl>
 <dt><code>defaultExport</code></dt>
 <dd>Имя объекта, который будет ссылаться на значение экспорта по умолчанию (дефолтный экспорт) из модуля.</dd>
 <dt><code>module-name</code></dt>
 <dd>Имя модуля для импорта. Это зачастую относительный или абсолютный путь к <code>.js</code> файлу модуля без указания расширения <code>.js</code>. Некоторые сборщики могут разрешать или даже требовать использования расширения; проверяйте своё рабочее окружение. Допускаются только строки с одиночными или двойными кавычками.</dd>
 <dt><code>name</code></dt>
 <dd>Имя локального объекта, который будет использован как своего рода пространство имен, ссылающееся на импортируемые значения.</dd>
</dl>

<dl>
 <dt><code>export, exportN</code></dt>
 <dd>Имена значений, которые будут импортированы.</dd>
</dl>

<dl>
 <dt><code>alias, aliasN</code></dt>
 <dd>Имена, которые будут ссылаться на импортируемые значения.</dd>
</dl>

<h2 id="Описание">Описание</h2>

<p>Параметр <code>name</code> это имя локального объекта, который будет использован как своего рода пространство имен, ссылающееся на импортируемые значения. Параметры <code>export</code> определяют отдельные именованные значения, в то время как <code>import * as name</code> импортирует все значения. Примеры ниже объясняют синтаксис.</p>

<h3 id="Импорт_всего_содержимого_модуля">Импорт всего содержимого модуля</h3>

<p>Этот код вставляет объект <code>myModule</code> в текущую область видимости, содержащую все экспортированные значения из модуля, находящегося в файле <code>/modules/my-module.js</code>.</p>

<pre class="brush: js">import * as <em>myModule</em> from '/modules/my-module.js';</pre>

<p>В данном случае, доступ к импортируемым значениям можно осуществить с использованием имени модуля (в данном случае "myModule") в качестве пространства имен. Например, если импортируемый выше модуль включает в себя экспорт метода <code>doAllTheAmazingThings()</code>, вы можете вызвать его так:</p>

<pre class="brush: js">myModule.doAllTheAmazingThings();</pre>

<h3 id="Импорт_единичного_значения_из_модуля">Импорт единичного значения из модуля</h3>

<p>Определенное ранее значение, названное <code>myExport,</code> которое было экспортировано из модуля <code>my-module</code> либо неявно (если модуль был экспортирован целиком), либо явно (с использованием инструкции {{jsxref("Statements/export", "export")}}), позволяет вставить <code>myExport</code> в текущую область видимости.</p>

<pre class="brush: js">import {myExport} from '/modules/my-module.js';</pre>

<h3 id="Импорт_нескольких_единичных_значений">Импорт нескольких единичных значений</h3>

<p>Этот код  вставляет оба значения <code>foo</code> и <code>bar</code> в текущую область видимости.</p>

<pre class="brush: js">import {foo, bar} from '/modules/my-module.js';</pre>

<h3 id="Импорт_значений_с_использованием_более_удобных_имен">Импорт значений с использованием более удобных имен</h3>

<p>Вы можете переименовать значения, когда импортируете их. Например, этот код вставляет <code>shortName</code> в текущую область видимости.</p>

<pre class="brush: js">import {reallyReallyLongModuleExportName as shortName}
  from '/modules/my-module.js';</pre>

<h3 id="Переименование_нескольких_значений_в_одном_импорте">Переименование нескольких значений в одном импорте</h3>

<p>Код, который импортирует несколько значений из модуля, используя более удобные имена.</p>

<pre class="brush: js">import {
  reallyReallyLongModuleExportName as shortName,
  anotherLongModuleName as short
} from '/modules/my-module.js';</pre>

<h3 id="Импорт_модуля_для_использования_его_побочного_эффекта">Импорт модуля для использования его побочного эффекта</h3>

<p>Импорт всего модуля только для использования побочного эффекта от его вызова, не импортируя что-либо. Это запускает глобальный код модуля, но в действительности не импортирует никаких значений.</p>

<pre class="brush: js">import '/modules/my-module.js';
</pre>

<h3 id="Импорт_значения_по_умолчанию">Импорт значения по умолчанию</h3>

<p>Есть возможность задать дефолтный {{jsxref("Statements/export", "export")}} (будь то объект, функция, класс или др.). Инструкция <code>import</code> затем может быть использована для импорта таких значений.</p>

<p>Простейшая версия прямого импорта значения по умолчанию:</p>

<pre class="brush: js">import myDefault from '/modules/my-module.js';
</pre>

<p>Возможно также использование такого синтаксиса с другими вариантами из перечисленных выше (импорт пространства имен или именованный импорт). В таком случае, импорт значения по умолчанию должен быть определён первым. Для примера:</p>

<pre class="brush: js">import myDefault, * as myModule from '/modules/my-module.js';
// myModule использовано как пространство имен</pre>

<p>или</p>

<pre class="brush: js">import myDefault, {foo, bar} from '/modules/my-module.js';
// именованный импорт конкретных значений</pre>

<h3 id="Импорт_переменных">Импорт переменных</h3>

<p>Если вы импортируете переменные, то в данной области видимости они ведут себя как константы.</p>

<p>Такой код выведет ошибку:</p>

<h5 id="my-module.js">my-module.js</h5>

<pre class="brush: js">export let a = 2;
export let b = 3;
</pre>

<h5 id="main.js">main.js</h5>

<pre class="brush: js">import {a, b} from '/modules/my-module.js';
a = 5;
b = 6;
// Uncaught TypeError: Assignment to constant variable.</pre>

<p>Для импорта можно воспользоваться объектом в котором хранятся эти переменные.</p>

<p>Такой код будет рабочим:</p>

<h5 id="my-module.js_2">my-module.js</h5>

<pre class="brush: js">export let obj = {a:2, b:4};
</pre>

<h5 id="main.js_2">main.js</h5>

<pre class="brush: js">import {obj} from '/modules/my-module.js';

obj.a = 1;
obj.b = 4;</pre>

<p>Учитывая, что <code>import</code> хранит именно ссылки на значения, экспортированные из внешнего модуля, то это можно использовать как замыкания.</p>

<h3 id="Динамический_импорт">Динамический импорт</h3>

<p>Ключевое слово <code>import</code> можно использовать как функцию для динамического импорта модулей. Вызов <code>import()</code> возвращает Promise.</p>

<pre class="brush: js">import('/modules/my-module.js')
  .then(module =&gt; {
    // Делаем что-нибудь с модулем
  })
</pre>

<p>Как следствие возврата Promise, с динамическим импортом можно использовать ключевое слово <code>await</code></p>

<pre class="brush: js">let module = await import('/modules/my-module.js');</pre>

<p>Обратите внимание, что несмотря на то, что динамический импорт выглядит как вызов функции, он им по сути не является, т.е. не наследует от <code>Function.prototype</code> и, как следствие, его невозможно использовать вместе с методами <code>.call</code>, <code>.apply</code> и <code>.bind </code></p>

<h2 id="Примеры">Примеры</h2>

<p>Импорт из вспомогательного модуля для помощи в обработке запроса AJAX JSON.</p>

<h3 id="Модуль_file.js">Модуль: file.js</h3>

<pre class="brush: js; highlight: [14]">function getJSON(url, callback) {
  let xhr = new XMLHttpRequest();
  xhr.onload = function () {
     callback(this.responseText)
  };
  xhr.open('GET', url, true);
  xhr.send();
}

export function getUsefulContents(url, callback) {
  getJSON(url, data =&gt; callback(JSON.parse(data)));
}
</pre>

<h3 id="Основной_код_main.js">Основной код: main.js</h3>

<pre class="brush: js">import { getUsefulContents } from '/modules/file.js';

getUsefulContents('http://www.example.com',
    data =&gt; { doSomethingUseful(data); });</pre>

<h3 id="Динамический_импорт_2">Динамический импорт</h3>

<p>Этот пример показывает, как можно загрузить на страницу дополнительный модуль в зависимости от действий пользователя (в данном случае, по клику на кнопку), а затем использовать функции из загруженного модуля. Промисы - это не единственный способ использовать динамический импорт. Функция <code>import()</code> также может использоваться совместно с <code>await</code>.</p>

<pre class="brush: js">const main = document.querySelector("main");
for (const link of document.querySelectorAll("nav &gt; a")) {
  link.addEventListener("click", e =&gt; {
    e.preventDefault();

    import('/modules/my-module.js')
      .then(module =&gt; {
        module.loadPageInto(main);
      })
      .catch(err =&gt; {
        main.textContent = err.message;
      });
  });
}</pre>

<h2 id="Спецификации">Спецификации</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Спецификация</th>
   <th scope="col">Статус</th>
   <th scope="col">Комментарий</th>
  </tr>
  <tr>
   <td>{{SpecName('ES2015', '#sec-imports', 'Imports')}}</td>
   <td>{{Spec2('ES2015')}}</td>
   <td>Начальное определение.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES2020', '#sec-imports', 'Imports')}}</td>
   <td>{{Spec2('ES2020')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-imports', 'Imports')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="Совместимость">Совместимость</h2>

<div class="hidden">
<p>The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
</div>

<p>{{Compat("javascript.statements.import")}}</p>

<h2 id="Смотри_также">Смотри также</h2>

<ul>
 <li>{{jsxref("Statements/export", "export")}}</li>
 <li><a href="https://blogs.windows.com/msedgedev/2016/05/17/es6-modules-and-beyond/">Previewing ES6 Modules and more from ES2015, ES2016 and beyond</a></li>
 <li><a href="https://hacks.mozilla.org/2015/08/es6-in-depth-modules/">ES6 in Depth: Modules</a>, Hacks blog post by Jason Orendorff</li>
 <li><a class="external" href="http://exploringjs.com/es6/ch_modules.html">Axel Rauschmayer's book: "Exploring JS: Modules"</a></li>
</ul>