Pull to refresh

JavaScript модули

Reading time 4 min
Views 18K
Original author: jsmodules.io
Перевод статьи «JavaScript Modules» с сайта jsmodules.io.

В новой версии JavaScript появится модульная система, главным образом вдохновленная идеей модулей Node.js.
В этой статье я расскажу, как это будет работать.

Создание модуля


В качестве упражнения, мы построим простой asap модуль, который позволит назначать выполнение действий «как только так сразу» асинхронным образом. В Node.js, вы можете сделать это при помощи process.nextTick, есть и разные подходы, которые работают во многих браузерах. Мы создадим модуль, который будет работать в любом окружении.1

Начнем с создания нового файла для нашего модуля. Назовём его asap.js. Модуль предоставляет единственную функцию, что называется экспорт по умолчанию(default export). Вы можете делать экспорт по умолчанию при помощи конструкции export default.
var asap;
var isNode = typeof process !== "undefined" &&
             {}.toString.call(process) === "[object process]";

if (isNode) {
  asap = process.nextTick;
} else if (typeof setImmediate !== "undefined") {
  asap = setImmediate;
} else {
  asap = setTimeout;
}

export default asap;

Импорт модуля


Чтобы импортировать asap из другого модуля, мы используем следующий синтаксис:
import asap from "asap";

asap(function() {
  console.log("hello async world!");
});

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

Именованный экспорт


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

Например, в jQuery есть один главный экспорт (функция jQuery) и несколько дополнительных именованных экспортов (ajax, getJSON, animate и пр.). В модуле Node.js mkdirp есть экспорт по умолчанию, который создает директорию и именованный экспорт под названием sync, который делает то же, но синхронно.

В нашем случае, в дополнение к экспорту по умолчанию, asap модуль может также предоставлять функцию later, которая назначает выполнение кода на момент, когда другие сетевые или UI процессы уже произошли.

Наш модуль выглядит так же, кроме того, что мы добавили новое объявление экспорта.
var asap;
var isNode = typeof process !== "undefined" &&
             {}.toString.call(process) === "[object process]";

if (isNode) {
  asap = process.nextTick;
} else if (typeof setImmediate !== "undefined") {
  asap = setImmediate;
} else {
  asap = setTimeout;
}

export default asap;
export var later = isNode ? process.setImmediate : asap;

Именованный импорт


Теперь, когда мы экспортировали later, мы можем импортировать его в другом модуле.
import { later } from "asap";

later(function() {
  console.log("Running after other network events");
});

Для любопытных, вы можете импортировать экспорт по умолчанию и именованные экспорты одной инструкцией импорта:
import asap, { later } from "asap";

И это все, что нужно сделать!

Удобства


Переименование именованного импорта

Иногда, импортируя именованный экспорт, вам нужно дать ему собственное локальное имя.
import { unlink as rm } from "fs";

rm(filename, function(err) { /* check errors */ });

Импорт в пространство имен

Может быть удобным, импортировать все именованные экспорты модуля в единственное локальное пространство имен2.
import * as fs from "fs";

fs.unlink(filename, function(err) { /* check errors */ });

Сокращенный способ экспорта

Вы можете делать любое объявление в JavaScript (например var или function) именованным экспортом предваряя его ключевым словом export.
// exports this function as "requestAnimationFrame"
export function requestAnimationFrame() {
  // cross-browser requestAnimationFrame
}

// exports document.location as "location"
export var location = document.location; 

Это также работает для новых объявлений, например class или let
// exports this class as "File"
export class File() { /* implementation */ }

// exports "0.6.3" as "VERSION"
export let VERSION = "0.6.3";

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

Вы можете экспортировать любое количество локальных переменных одной инструкцией.
function getJSON() {
  // implementation
}

function postJSON() {
  // implementation
}

function animate() {
  // implementation
}

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

Особенности


JavaScript модули имеют несколько приятных особенностей, которые упрощают их использование и рефакторинг.
  • JavaScript модули поддерживают отложенное связывание между модулями, как для именованного экспорта так и для экспорта по умолчанию. Оно просто работает.
  • JavaScript модули разделяют имена существующие в экспорте по умолчанию (и цепочках прототипов) и другим именованным экспортом, предотвращая конфликты.
  • С JavaScript модулями проще определить, что именно вы импортируете просто посмотрев на синтаксис. Это улучшает сообщения об ошибках, а также упрощает создание таких инструментов, как browserify или JSHint, которые должны работать надежно.

Примечания


1 Для реального использования данный модуль должен бы быть более детализированным, но для нашего примера этого достаточно.
2 Примечание переводчика: похоже, что импорт в пространство имен будет выглядеть следующим образом module fs from "fs";
Tags:
Hubs:
+36
Comments 10
Comments Comments 10

Articles