Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Проблема 5. Отсутствие изоляции кода разных файлов

Поиск

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

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

Каждый модуль прямо определяет:

l что он хочет экспортировать наружу для других модулей;

l а что хочет импортировать себе, из других модулей.

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

Улучшать код функции loadScript и прописывать собственную систему модулей не требуется. Всё уже придумали за нас. Рассмотрим имеющиеся на текущий момент системы модульности. А в качестве практического задания попробуем улучшить функцию loadScript.

Системы модулей

Итак, что же такое модуль? Эдди Османи, автор книги «Паттерны для масштабируемых JavaScript-приложений», даёт следующее определение модуля:

«Модуль — это популярная реализация паттерна, инкапсулирующего приватную информацию, состояние и структуру. Паттерн «модуль» возвращает только публичную часть API, оставляя всё остальное доступным только внутри замыканий».

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

Как мы выяснили выше по тексту, код записывается и без использования модулей. Но модуль позволяет решить ряд проблем:

1. Управлять зависимостями, легко изменяя зависимости без переписывания кода.

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

3. Инкапсулировать код, скрывая его внутри модуля без изменений.

4. Переиспользовать код, избавляясь от постоянного написания одного и того же.

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

Так как модуль — это паттерн, то в мире JavaScript есть несколько его реализаций. Одни из самых популярных считаются CommonJS, AMD (RequireJS), UMD, ECMAScript Modules (ES2015 Modules). На самом деле, систем модулей намного больше. Мы рассмотрим только самые популярные, чтобы понять общее направление развития модулей в языке. Подробно остановимся лишь на ECMAScript Modules, как на системе модулей, появившейся в стандарте языка и поставившей точку на всех остальных.

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

const translates = {   en: "Hello, ",   ru: "Привет, ", } function sayHello(name, lang = "en") {   return translates[lang] + name; } console.log(sayHello("Ivan"));

 

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

Модули CommonJS

Модульная система CommonJS появилась в 2009 году. Она предназначается для использования в серверном окружении JavaScript. В первую очередь, в Node.js.

Для загрузки модуля вызывается функция require(), а экспортируемые данные присваиваются как свойства объекту module.exports. Простой пример выглядит так:

Файл greeting.js:

const translates = {   en: "Hello, ",   ru: "Привет, ", } function sayHello(name, lang = "en") {   return translates[lang] + name; } module.exports = sayHello;

 

Файл main.js:

const { sayHello } = require('./greeting'); console.log(sayHello("Ivan"));

 

Теперь мы экспортируем только функцию sayHello. Это значит, что константа translates больше недоступна извне.

Так как module и require не считаются встроенными конструкциями JavaScript, Node.js оборачивает код каждого файла в такую конструкцию:

(function (exports, require, module, __filename, __dirname) { // Your code is injected here! });

 

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

Модули AMD (RequireJS)

Модульная система AMD появилась в 2009 году и расшифровывается как Asynchronous Module Definition. Не стоит путать с производителем процессоров для компьютеров. AMD возникла как ответ на полностью синхронную систему модулей CommonJS. Она позволяет загружать модули в асинхронном режиме.

Для определения модуля требуется вызвать функцию define. Если первым аргументом передать в неё массив, он расценится как список зависимостей для этого модуля. В любом случае код модуля нужно указывать в функции, которая будет выполнена. Только когда все модули, указанные как зависимости, загрузятся.

Файл greeting.js:

define(function() {   const translates = {          en: "Hello, ",          ru: "Привет, ",   }   function sayHello(name, lang = "en") {          return translates[lang] + name;   }   return { sayHello }; });

Файл main.js:

define(["greeting"], function({ sayHello }) {   console.log(sayHello("Ivan")); });

Для использования AMD в браузере нужно использовать стороннюю библиотеку RequireJS. Она предоставляет API для работы с функцией define и асинхронную загрузку файлов.

Модули UMD

CommonJS и AMD активно конкурировали между собой, но AMD эту схватку проиграл. Однако разный способ объявления модулей в этих двух системах приносил много хлопот разработчикам библиотек. Они не знали, в какой именно системе модульности будет использоваться их код. Поэтому в 2011 году появился способ написания модулей для работы в обеих системах — UMD (Universal Module Definition).

Файл greeting.js:

(function(define) { define(function () {    const translates = {                              en: "Hello, ",                              ru: "Привет, ",                       }                       function sayHello(name, lang = "en") {                              return translates[lang] + name;                       }                                       return { sayHello }; }); }(typeof module === 'object' && module.exports && typeof define!== 'function'? function (factory) { module.exports = factory(); }: define));

 

Теперь у нас есть самовызывающаяся функция. Она проверяет, определился ли у нас в глобальной области module или define. Писать такую большую обёртку самостоятельно не придётся, если воспользоваться инструментами сборки, о которых мы поговорим на следующем уроке.



Поделиться:


Последнее изменение этой страницы: 2022-01-22; просмотров: 55; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.237.52 (0.009 с.)