В новой версии 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 */ });
Импорт в пространство имен
Может быть удобным, импортировать все именованные экспорты модуля в единственное локальное пространство имен.
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 Для реального использования данный модуль должен бы быть более детализированным, но для нашего примера этого достаточно.
ссылка на оригинал статьи http://habrahabr.ru/post/229329/
Добавить комментарий