Загрузка модуля ES6, вы действительно полностью это понимаете?

внешний интерфейс JavaScript

Это 12-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления

Синтаксис модуля

Обзор

Исторически сложилось так, что в JavaScript никогда не было модульной системы, и невозможно разбить большую программу на маленькие файлы, которые зависят друг от друга, а затем собрать их простым способом. Эта функция есть и в других языках, например, в Ruby.require, Питонimport, даже в CSS есть@import, но JavaScript не поддерживает это, что является огромным препятствием для разработки больших и сложных проектов.

До ES6 сообщество разработало несколько схем загрузки модулей, наиболее важными из которых были CommonJS и AMD. Первый для сервера, а второй для браузера. На уровне языковых стандартов ES6 реализует модульную функцию, и реализация достаточно проста, она может полностью заменить спецификации CommonJS и AMD и стать общим модульным решением для браузеров и серверов.

Идея дизайна модулей ES6 состоит в том, чтобы быть как можно более статичными, чтобы зависимости модулей, а также входные и выходные переменные можно было определить во время компиляции. Модули CommonJS и AMD могут определять эти вещи только во время выполнения. Например, модули CommonJS являются объектами, и свойства объекта необходимо искать при вводе.

// CommonJS模块
let { stat, exists, readfile } = require('fs');

// 等同于
let _fs = require('fs');
let stat = _fs.stat;
let exists = _fs.exists;
let readfile = _fs.readfile;

Суть приведенного выше кода в общей загрузкеfsмодуль (т.е. загрузитьfsвсе методы), что дает объект (_fs), а затем прочитать 3 метода из этого объекта. Этот тип загрузки называется "загрузкой во время выполнения", потому что только среда выполнения может получить этот объект, поэтому нет возможности выполнить "статическую оптимизацию" во время компиляции.

Модули ES6 не являются объектами, ониexportКоманда явно указывает выходной код, а затем передаетimportввод команды.

// ES6模块
import { stat, exists, readFile } from 'fs';

Суть приведенного выше кода изfsМодуль загружает 3 метода, остальные методы не загружаются. Этот тип загрузки называется «загрузкой во время компиляции» или статической загрузкой, то есть ES6 может завершать загрузку модуля во время компиляции, что более эффективно, чем метод загрузки модулей CommonJS. Конечно, это также делает невозможным обращение к самому модулю ES6, поскольку он не является объектом.

Поскольку модули ES6 загружаются во время компиляции, возможен статический анализ. С его помощью можно еще больше расширить синтаксис JavaScript, например, ввести макросы и системы типов, чего можно достичь только с помощью статического анализа.

В дополнение к различным преимуществам статической загрузки модули ES6 имеют следующие преимущества.

  • Больше не нуженUMDФормат модуля теперь доступен, и в будущем как серверы, так и браузеры будут поддерживать формат модуля ES6. В настоящее время с помощью различных библиотек инструментов это действительно сделано.
  • В будущем новые API-интерфейсы браузеров могут предоставляться в формате модуля, и их больше не нужно превращать в глобальные переменные илиnavigatorсвойства объекта.
  • Объекты больше не требуются в качестве пространств имен (например,Mathобъект), в дальнейшем эти функции могут обеспечиваться модулями.

В этой главе представлен синтаксис модулей ES6, а в следующей главе описано, как загружать модули ES6 в браузере и Node.

строгий режим

Модули ES6 автоматически используют строгий режим, независимо от того, добавляете ли вы"use strict";.

Строгий режим в основном имеет следующие ограничения.

  • Переменные должны быть объявлены перед использованием
  • Параметры функции не могут иметь атрибуты с одинаковыми именами, иначе будет сообщено об ошибке
  • нельзя использоватьwithутверждение
  • Нельзя присваивать значения свойствам только для чтения, иначе будет сообщено об ошибке
  • Вы не можете использовать префикс 0 для представления восьмеричного числа, иначе будет сообщено об ошибке
  • Невозможно удалить неудаляемые атрибуты, иначе будет сообщено об ошибке
  • переменная не может быть удаленаdelete prop, будет выдано сообщение об ошибке, удалить можно только атрибутdelete global[prop]
  • evalне вводит переменные во внешнюю область видимости
  • evalа такжеargumentsнельзя переназначить
  • argumentsИзменения параметров функции не отражаются автоматически
  • нельзя использоватьarguments.callee
  • нельзя использоватьarguments.caller
  • запретитьthisуказывает на глобальный объект
  • нельзя использоватьfn.callerа такжеfn.argumentsПолучить стек вызовов функций
  • Добавлены зарезервированные слова (например,protected,staticа такжеinterface)

Все вышеперечисленные ограничения должны соблюдаться модулями. Поскольку строгий режим был введен в ES5 и не относится к ES6, обратитесь к соответствующим книгам по ES5, которые не будут подробно описаны в этой книге.

Из них особое внимание следует обратить наthisпределы. Среди модулей ES6 самый высокий уровеньthisнаправлениеundefined, т.е. не должен использоваться в коде верхнего уровняthis.

команда экспорта

Функция модуля в основном состоит из двух команд:exportа такжеimport.exportКоманда используется для указания внешнего интерфейса модуля,importКоманды используются для ввода функций, предоставляемых другими модулями.

Модуль представляет собой один файл. Все переменные внутри этого файла не могут быть получены извне. Если вы хотите, чтобы снаружи можно было прочитать переменную внутри модуля, вы должны использоватьexportключевое слово выводит переменную. Ниже приведен файл JS, в котором используетсяexportВыходная переменная команды.

// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;

Приведенный выше кодprofile.jsфайл, в котором хранится информация о пользователе. ES6 рассматривает его как модуль, который используетexportКоманда выводит наружу три переменные.

exportКроме вышеперечисленного, есть еще один способ записи.

// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export { firstName, lastName, year };

Приведенный выше код находится вexportПосле команды используйте фигурные скобки, чтобы указать набор переменных для вывода. Это то же самое, что и предыдущее письмо (помещено непосредственно вvarоператор) эквивалентны, но это должно быть предпочтительным. Потому что таким образом в конце скрипта можно сразу увидеть, какие переменные выводятся.

exportПомимо выходных переменных, команды также могут выводить функции или классы.

export function multiply(x, y) {
  return x * y;
};

Вышеприведенный код выводит функцию извнеmultiply.

как правило,exportВыходная переменная имеет исходное имя, но ее можно использоватьasПереименование ключевого слова.

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};

Используйте приведенный выше кодasключевое слово, переименованная функцияv1а такжеv2внешний интерфейс. После переименования,v2Может быть выведен дважды с разными именами.

Важно отметить, чтоexportКоманда указывает внешний интерфейс и должна установить однозначное соответствие с переменными внутри модуля.

// 报错
export 1;

// 报错
var m = 1;
export m;

Приведенные выше два способа записи сообщат об ошибке, поскольку внешний интерфейс не предусмотрен. Первый метод записи выводит 1 напрямую, а второй метод записи передает переменнуюmили вывести 1 напрямую.1Просто значение, а не интерфейс. Правильное написание выглядит следующим образом.

// 写法一
export var m = 1;

// 写法二
var m = 1;
export {m};

// 写法三
var n = 1;
export {n as m};

Вышеупомянутые три способа написания правильны, указывая внешний интерфейсm. Другие сценарии могут получить значение через этот интерфейс.1. Суть их в том, что между именем интерфейса и переменными внутри модуля устанавливается однозначное соответствие.

такой же,functionа такжеclassВывод также должен следовать этому способу написания.

// 报错
function f() {}
export f;

// 正确
export function f() {};

// 正确
function f() {}
export {f};

Кроме того,exportИнтерфейс, выводимый оператором, имеет отношение динамической привязки с соответствующим значением, то есть через этот интерфейс можно получить значение в реальном времени внутри модуля.

export var foo = 'bar';
setTimeout(() => foo = 'baz', 500);

Приведенный выше код выводит переменнуюfoo, значениеbar, через 500 миллисекунд становитсяbaz.

Это полностью отличается от спецификации CommonJS. Вывод модуля CommonJS представляет собой кеш значений, динамическое обновление отсутствует.Подробности см. в разделе «Реализация загрузки модуля» ниже.

наконец,exportКоманды могут появляться в любом месте модуля, если они находятся на верхнем уровне модуля. Если он находится в области блочного уровня, он сообщит об ошибке, следующий разделimportТо же самое касается команд. Это связано с тем, что в условном блоке кода невозможно выполнить статическую оптимизацию, что нарушает первоначальный замысел конструкции модуля ES6.

function foo() {
  export default 'bar' // SyntaxError
}
foo()

В приведенном выше кодеexportОператор помещается в функцию, и результатом является ошибка.

команда импорта

использоватьexportПосле того, как команда определит внешний интерфейс модуля, другие файлы JS могут передаватьсяimportкоманда для загрузки этого модуля.

// main.js
import { firstName, lastName, year } from './profile.js';

function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}

код вышеimportкоманда для загрузкиprofile.jsфайл и входные переменные из него.importКоманда принимает пару фигурных скобок, определяющих имя переменной для импорта из других модулей. Имя переменной внутри фигурных скобок должно совпадать с именем импортируемого модуля (profile.js) Имя внешнего интерфейса одинаково.

Если вы хотите повторно ввести имя для переменной,importкоманда для использованияasключевое слово, чтобы переименовать введенную переменную.

import { lastName as surname } from './profile.js';

importПеременные, введенные командой, доступны только для чтения, потому что по своей природе это интерфейс ввода. То есть нельзя переписывать интерфейс в скрипте, загружающем модуль.

import {a} from './xxx.js'

a = {}; // Syntax Error : 'a' is read-only;

В приведенном выше коде скрипт загружает переменнуюa, переназначение сообщит об ошибке, т.к.aявляется интерфейсом только для чтения. но еслиaэто объект, переписатьaсвойства разрешены.

import {a} from './xxx.js'

a.foo = 'hello'; // 合法操作

В приведенном выше кодеaсвойства могут быть успешно перезаписаны, и другие модули также могут прочитать перезаписанное значение. Однако такой способ записи трудно проверить на наличие ошибок, рекомендуется, чтобы все входные переменные считались полностью доступными только для чтения, а их свойства не должны были легко изменяться.

importНазадfromУказывает расположение файла модуля, которое может быть относительным или абсолютным путем. Если пути нет, а есть только имя модуля, то должен быть файл конфигурации, который сообщает движку JavaScript, где находится модуль.

import { myMethod } from 'util';

В приведенном выше кодеutilИмя файла модуля. Так как у него нет пути, он должен быть настроен, чтобы сообщить двигателю, как получить этот модуль.

Уведомление,importКоманда имеет эффект подъема и будет поднята на голову всего модуля, который выполняется первым.

foo();

import { foo } from 'my_module';

Приведенный выше код не выдаст ошибку, потому чтоimportреализация раньше, чемfooвызов. Суть такого поведения в том, чтоimportКоманды выполняются на этапе компиляции до запуска кода.

из-заimportОн выполняется статически, поэтому нельзя использовать выражения и переменные, которые представляют собой синтаксические конструкции, которые получают результаты только во время выполнения.

// 报错
import { 'f' + 'oo' } from 'my_module';

// 报错
let module = 'my_module';
import { foo } from module;

// 报错
if (x === 1) {
  import { foo } from 'module1';
} else {
  import { foo } from 'module2';
}

Вышеупомянутые три способа записи сообщат об ошибке, потому что они используют выражения, переменные иifструктура. На этапе статического анализа ни одна из этих грамматик не может получить значение.

наконец,importОператор выполняет загруженный модуль, поэтому его можно записать следующим образом.

import 'lodash';

Приведенный выше код просто выполняетсяlodashмодуль, но не вводите никаких значений.

Если одно и то же предложение повторяется несколько разimportоператор, то он будет выполнен только один раз, а не несколько раз.

import 'lodash';
import 'lodash';

Приведенный выше код загружается дваждыlodash, но только один раз.

import { foo } from 'my_module';
import { bar } from 'my_module';

// 等同于
import { foo, bar } from 'my_module';

В приведенном выше коде, хотяfooа такжеbarзагружается в два оператора, но они соответствуют одному и тому жеmy_moduleмодуль. То есть,importОператор представляет собой шаблон Singleton.

На этом этапе, посредством транскодирования Babel, модуль CommonJSrequireКоманды и модули ES6importКоманды можно писать в этом же модуле, но лучше этого не делать. потому чтоimportВыполняется на этапе статического разрешения, поэтому он выполняется первым в модуле. Приведенный ниже код может не дать ожидаемого результата.

require('core-js/modules/es6.symbol');
require('core-js/modules/es6.promise');
import React from 'React';

Общая загрузка модулей

Помимо указания определенного выходного значения для загрузки, вы также можете использовать общую нагрузку, то есть со звездочкой (*) указывает объект, на который загружаются все выходные значения.

Ниже приведенcircle.jsфайл, который выводит два методаareaа такжеcircumference.

// circle.js

export function area(radius) {
  return Math.PI * radius * radius;
}

export function circumference(radius) {
  return 2 * Math.PI * radius;
}

Теперь загрузите этот модуль.

// main.js

import { area, circumference } from './circle';

console.log('圆面积:' + area(4));
console.log('圆周长:' + circumference(14));

Вышеупомянутый метод записи заключается в том, чтобы указать методы для загрузки один за другим.Метод записи общей загрузки заключается в следующем.

import * as circle from './circle';

console.log('圆面积:' + circle.area(4));
console.log('圆周长:' + circle.circumference(14));

Обратите внимание, что объект в целом, куда загружается модуль (в примереcircle), должны быть доступны для статического анализа, поэтому изменения во время выполнения не допускаются. Следующие варианты написания не допускаются.

import * as circle from './circle';

// 下面两行都是不允许的
circle.foo = 'hello';
circle.area = function () {};

команда экспорта по умолчанию

Как видно из предыдущего примера, использованиеimportПри выполнении команды пользователю необходимо знать имя загружаемой переменной или функции, иначе она не может быть загружена. Однако пользователи определенно хотят быстро приступить к работе и могут не захотеть читать документацию, чтобы понять, какие свойства и методы есть у модуля.

Чтобы упростить пользователям загрузку модулей без чтения документации, используйтеexport defaultКоманда, укажите вывод по умолчанию для модуля.

// export-default.js
export default function () {
  console.log('foo');
}

Приведенный выше код представляет собой файл модуляexport-default.js, вывод которого по умолчанию является функцией.

Когда другие модули загружают этот модуль,importКоманды могут присвоить анонимной функции любое имя.

// import-default.js
import customName from './export-default';
customName(); // 'foo'

код вышеimportкоманда, на которую можно указать любое имяexport-default.jsМетоду вывода не нужно знать имя функции, выводимое исходным модулем. Следует отметить, что в это времяimportПосле команды не используйте фигурные скобки.

export defaultТакже возможно использовать команды перед неанонимными функциями.

// export-default.js
export default function foo() {
  console.log('foo');
}

// 或者写成

function foo() {
  console.log('foo');
}

export default foo;

В приведенном выше кодеfooимя функцииfoo, недействителен вне модуля. При загрузке загружается как анонимная функция.

Давайте сравним вывод по умолчанию и обычный вывод.

// 第一组
export default function crc32() { // 输出
  // ...
}

import crc32 from 'crc32'; // 输入

// 第二组
export function crc32() { // 输出
  // ...
};

import {crc32} from 'crc32'; // 输入

Два набора методов написания приведенного выше кода, первый набор должен использоватьexport defaultкогда соответствующийimportПостановка не требует использования фигурных скобок, вторая группа не использоваласьexport defaultкогда соответствующийimportОператоры требуют фигурных скобок.

export defaultКоманда используется для указания вывода модуля по умолчанию. Очевидно, модуль может иметь только один выход по умолчанию, поэтомуexport defaultКоманду можно использовать только один раз. Поэтому после команды импорта фигурные скобки не используются, т.к. только единственно возможное соответствиеexport defaultЗаказ.

По сути,export defaultзаключается в выводеdefaultпеременной или методу, то система позволяет дать ему любое имя. Поэтому справедливо следующее обозначение.

// modules.js
function add(x, y) {
  return x * y;
}
export {add as default};
// 等同于
// export default add;

// app.js
import { default as foo } from 'modules';
// 等同于
// import foo from 'modules';

просто такexport defaultНа самом деле команда просто выводитdefaultпеременная, поэтому за ней не может следовать оператор объявления переменной.

// 正确
export var a = 1;

// 正确
var a = 1;
export default a;

// 错误
export default var a = 1;

В приведенном выше кодеexport default aозначает, что переменнаяaприсвоить значение переменнойdefault. Поэтому последний способ записи сообщит об ошибке.

Точно так же, потому чтоexport defaultСуть команды заключается в том, чтобы присвоить следующее значениеdefaultпеременная, так что вы можете напрямую записать значение вexport defaultПозже.

// 正确
export default 42;

// 报错
export 42;

В приведенном выше коде последнее предложение сообщает об ошибке, поскольку внешний интерфейс не указан, а предыдущее предложение указывает, что внешний интерфейсdefault.

имеютexport defaultКоманды, вход в модуль очень интуитивно понятен, в качестве примера возьмем ввод модуля lodash.

import _ from 'lodash';

Если вы хотите быть вimportВ операторе введите метод по умолчанию и другие интерфейсы одновременно, что можно записать следующим образом.

import _, { each, forEach } from 'lodash';

соответствующий приведенному выше кодуexportЗаявление выглядит следующим образом.

export default function (obj) {
  // ···
}

export function each(obj, iterator, context) {
  // ···
}

export { each as forEach };

Последняя строка приведенного выше кода означает, что раскрытиеforEachинтерфейс, по умолчаниюeachИнтерфейсы, а именноforEachа такжеeachуказать на один и тот же метод.

export defaultТакже может использоваться для вывода классов.

// MyClass.js
export default class { ... }

// main.js
import MyClass from 'MyClass';
let o = new MyClass();

Сочетание экспорта и импорта

Если в модуле сначала ввести, а затем вывести один и тот же модуль,importЗаявления можно комбинировать сexportЗаявления пишутся слитно.

export { foo, bar } from 'my_module';

// 可以简单理解为
import { foo, bar } from 'my_module';
export { foo, bar };

В приведенном выше кодеexportа такжеimportОператоры можно объединять вместе и записывать в одну строку. Но следует отметить, что после написания строки,fooа такжеbarНа самом деле он не импортируется в текущий модуль, но эквивалентен пробросу этих двух интерфейсов во внешний мир, так что текущий модуль нельзя использовать напрямую.fooа такжеbar.

Таким же образом можно записать переименование интерфейса и общий вывод модуля.

// 接口改名
export { foo as myFoo } from 'my_module';

// 整体输出
export * from 'my_module';

Интерфейс по умолчанию написан следующим образом.

export { default } from 'foo';

Способ изменения именованного интерфейса на интерфейс по умолчанию следующий.

export { es6 as default } from './someModule';

// 等同于
import { es6 } from './someModule';
export default es6;

Точно так же интерфейс по умолчанию можно переименовать в именованный интерфейс.

export { default as es6 } from './someModule';

До ES2020 былimportЗаявление, нет соответствующего составного письма.

import * as someIdentifier from "someModule";

ES2020Добавил это правописание.

export * as ns from "mod";

// 等同于
import * as ns from "mod";
export {ns};

Наследование модулей

Также возможно наследование между модулями.

Предположим, естьcircleplusмодуль, унаследованныйcircleмодуль.

// circleplus.js

export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
  return Math.exp(x);
}

в коде вышеexport *, что указывает на то, что выходcircleВсе свойства и методы модуля. Уведомление,export *команда игнорируетсяcircleмодульныйdefaultметод. Затем приведенный выше код выводит пользовательскийeПеременные и методы по умолчанию.

В это время вы также можетеcircleсвойства или методы, переименуйте их, а затем выведите.

// circleplus.js

export { area as circleArea } from 'circle';

Приведенный выше код означает, что только выводcircleмодульныйareaметод и переименуйте его вcircleArea.

Способ загрузки вышеуказанного модуля следующий.

// main.js

import * as math from 'circleplus';
import exp from 'circleplus';
console.log(exp(math.e));

в коде вышеimport expсказал, будетcircleplusМетод модуля по умолчанию загружается какexpметод.

Кросс-модульные константы

Введение в эту книгуconstКогда приказали,constОбъявленные константы действительны только в текущем блоке кода. Если вы хотите установить постоянные в модулях (то есть по нескольким файлам), или если значение должно использоваться несколькими модулями, вы можете использовать следующий метод записи.

// constants.js 模块
export const A = 1;
export const B = 3;
export const C = 4;

// test1.js 模块
import * as constants from './constants';
console.log(constants.A); // 1
console.log(constants.B); // 3

// test2.js 模块
import {A, B} from './constants';
console.log(A); // 1
console.log(B); // 3

Если вы хотите использовать, вы можете построить специализированныйconstantsкаталоге, записывайте различные константы в разные файлы и сохраняйте их в этом каталоге.

// constants/db.js
export const db = {
  url: 'http://my.couchdbserver.local:5984',
  admin_username: 'admin',
  admin_password: 'admin password'
};

// constants/user.js
export const users = ['root', 'admin', 'staff', 'ceo', 'chief', 'moderator'];

Затем константы, выводимые из этих файлов, объединяются вindex.jsв.

// constants/index.js
export {db} from './db';
export {users} from './users';

При использовании напрямую загружайтеindex.jsВот и все.

// script.js
import {db, users} from './constants/index';

import()

Введение

Как упоминалось ранее,importКоманды JavaScript являются механизмом статического анализа, первая реализация других утверждений в модуле (importКоманда называется «соединение», привязка на самом деле более уместна). Поэтому следующий код сообщит об ошибке.

// 报错
if (x === 2) {
  import MyModual from './myModual';
}

В приведенном выше коде движок обрабатываетimportОператоры компилируются во время компиляции и не будут анализироваться или выполняться в это время.ifзаявление, так чтоimportзаявление вifБлок кода не имеет смысла, поэтому вместо ошибки времени выполнения сообщается о синтаксической ошибке. То есть,importа такжеexportКоманды могут находиться только на верхнем уровне модуля, а не внутри блока кода (например, вifвнутри блока кода или внутри функции).

Такой дизайн полезен для повышения эффективности компилятора, но также делает невозможной загрузку модулей во время выполнения. Синтаксически условная загрузка невозможна. еслиimportкоманда для замены узлаrequireметод, который создает препятствие. потому чтоrequireмодуль загрузки во время выполнения,importкоманда не может быть замененаrequireфункция динамической загрузки.

const path = './' + fileName;
const myModual = require(path);

Приведенное выше утверждение является динамической загрузкой,requireКакой именно модуль загружать, известно только во время выполнения.importКомандование не может этого сделать.

Предложение ES2020представлятьimport()функция поддержки динамической загрузки модулей.

import(specifier)

В приведенном выше кодеimportаргументы функцииspecifier, указав расположение модуля для загрузки.importКакие параметры может принимать команда,import()Функция может принимать любые параметры, главное отличие между ними в том, что последняя загружается динамически.

import()Возвращает объект Promise. Ниже приведен пример.

const main = document.querySelector('main');

import(`./section-modules/${someVariable}.js`)
  .then(module => {
    module.loadPageInto(main);
  })
  .catch(err => {
    main.textContent = err.message;
  });

import()Функции можно использовать где угодно, не только в модулях, но и в немодульных скриптах. Он выполняется во время выполнения, то есть при выполнении этого предложения будет загружен указанный модуль. Кроме того,import()Функция не имеет отношения статического соединения с загруженным модулем, что также связано сimportФразы не совпадают.import()Похоже на узелrequireметод, основное отличие состоит в том, что первый — это асинхронная загрузка, а второй — синхронная загрузка.

Приложения

Нижеimport()некоторые применимые случаи.

(1) Загрузка по требованию.

import()Модуль может быть загружен при необходимости.

button.addEventListener('click', event => {
  import('./dialogBox.js')
  .then(dialogBox => {
    dialogBox.open();
  })
  .catch(error => {
    /* Error handling */
  })
});

В приведенном выше кодеimport()метод вclickВ функции прослушивателя событий этот модуль будет загружен только тогда, когда пользователь нажмет кнопку.

(2) Условная нагрузка

import()можно разместить вifБлоки кода в зависимости от ситуации загружают разные модули.

if (condition) {
  import('moduleA').then(...);
} else {
  import('moduleB').then(...);
}

В приведенном выше коде, если выполняются условия, загружается модуль A, в противном случае загружается модуль B.

(3) Путь к динамическому модулю

import()Разрешить динамическое создание путей к модулям.

import(f())
.then(...);

В приведенном выше коде в соответствии с функциейfВозвращаемый результат загружает разные модули.

будь осторожен

import()После того, как модуль будет успешно загружен, модуль будет использоваться как объект какthenпараметры метода. Следовательно, выходной интерфейс можно получить, используя синтаксис назначения деструктуризации объекта.

import('./myModule.js')
.then(({export1, export2}) => {
  // ...·
});

В приведенном выше кодеexport1а такжеexport2обеmyModule.jsВыходной интерфейс можно получить путем деструктуризации.

Если модульdefaultВыходной интерфейс можно получить напрямую с параметрами.

import('./myModule.js')
.then(myModule => {
  console.log(myModule.default);
});

Приведенный выше код также может использовать форму именованного ввода.

import('./myModule.js')
.then(({default: theDefault}) => {
  console.log(theDefault);
});

Если вы хотите загрузить несколько модулей одновременно, вы можете использовать следующий метод записи.

Promise.all([
  import('./module1.js'),
  import('./module2.js'),
  import('./module3.js'),
])
.then(([module1, module2, module3]) => {
   ···
});

import()Также может использоваться в асинхронных функциях.

async function main() {
  const myModule = await import('./myModule.js');
  const {export1, export2} = await import('./myModule.js');
  const [module1, module2, module3] =
    await Promise.all([
      import('./module1.js'),
      import('./module2.js'),
      import('./module3.js'),
    ]);
}
main();