Понимание JavaScript модулей

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

Ближайшим аналогом в Java - это Java классы. Однако JavaScript модули экспортируют значение вместо определения типа. На практике, большинство JavaScript модулей экспортируют литерал объекта, функцию или конструктор. Модули, которые экспортируют строку, содержащую HTML шаблон или CSS таблицу, также довольно распостранены.

ECMAScript как JavaScript стандарт, ожидает утверждения итоговой спецификации модулей в ECMAScript версии 6 в конце 2014 года. Но скорее всего эти модули невозможно будет использовать на рабочих приложениях вплоть до 2016 года из-за долгих циклов обновлений браузеров и операционных систем.

Тем временем, два де-факто формата модулей развились. Asynchronous Module Definition (AMD) является наиболее популярным для кода на стороне клиента, в то время как node.js модули (расширение к CommonJS Modules/1.1) является ведущим шаблоном серверного окружения. Universal Module Definition (UMD) является набором шаблонов, которые пытаются преодолеть конфликты между AMD и node.js, предоставляя разрабатывать код одного формата, а не нескольких или конвертировать из других форматов на этапе сборки.

Asynchronous Module Definition

define(['store/customer', 'when'], function (customerStore, when) {
    return function (id) {
        return when(id).then(customerStore.load);
    };
});

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

Фабричная функция может экспортировать любой JavaScript тип, но обычно разработчики экспортируют объекты, функции и конструкторы. Модули, которые экспортируют функции или конструкторы, называются "function-modules" и "constructor-modules" соответственно.

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

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

node.js модули

var customerStore = require('store/customer');
var when = require('when');

module.exports = function (id) {
    return when(id).then(customerStore.load);
};

node.js примерно соответствует CommonJS Modules/1.1, определяя, как должно быть введено дерево локальных переменных: exports, require и module. В CommonJS модуль экспортирует значения путем присвоения значений параметрам объекта exports. Функция require импортирует другие модули по их идентификаторам. Объект module предоставляет метаданные о текущем модуле, такие как его is и uri.

Однако, обратите внимание, что во фрагменте node.js кода выше не использовался exports объект. Вместо этого, он назначен значению module.exports. module.exports является node.js расширением, которое позволяет разработчикам экспортировать не объектные значения.

ES6 модули

import { load } from 'store/customer';
import when from 'when';

export default = function (id) {
    return when(id).then(load);
};

ECMAScript 6 модули используют зарезервированные слова export и import.

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

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

Поскольку экспортируемые значения являются переменными, они всегда именованы. Кроме того, модуль может также определять экспортируемое значение по умолчанию. Модуль может объявлять до одного экспортируемого значения по умолчанию, именуя как "default".

Для импортирования и привязки к модулю экспорта по умолчанию, опустите фигурные скобки в выражении import:

import when from 'when';
import и export должны быть использованы в верхней области видимости блока. Вложенные import или export блоки будут бросать исключение SyntaxError.

JavaScript пакеты

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

С оригинальным текстом урока вы можете ознакомиться на spring.io.

comments powered by Disqus