Полный цикл в digital

Модульное программирование

Чтобы продемонстрировать модульное программирование, создадим для примера следующие файлы:

  1. index.html
  2. functions.js
  3. script.js

Создаем файл index.html в текстовом редакторе и добавляем в него следующий код:

index.html<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JavaScript Modules</title>
    </head>
    <body>
    <h1>Answers</h1>
    <h2><strong id="x"></strong> and <strong id="y"></strong></h2>
    <h3>Addition</h3>
    <p id="addition"></p>
    <h3>Subtraction</h3>
    <p id="subtraction"></p>
    <h3>Multiplication</h3>
    <p id="multiplication"></p>
    <h3>Division</h3>
    <p id="division"></p>
    <script src="functions.js"></script>
    <script src="script.js"></script>
    </body>
</html>

Создаем файл functions.js и добавляем в него следующий код:

functions.jsfunction sum(x, y) {
return x + y
}
function difference(x, y) {
return x - y
}
function product(x, y) {
return x * y
}
function quotient(x, y) {
return x / y
}

Создаем файл script.js который определяет значения переменных x и y, применяет к их значениям математические функции и отображает результат:

script.jsconst x = 10
const y = 5
document.getElementById('x').textContent = x
document.getElementById('y').textContent = y
document.getElementById('addition').textContent = sum(x, y)
document.getElementById('subtraction').textContent = difference(x, y)
document.getElementById('multiplication').textContent = product(x, y)
document.getElementById('division').textContent = quotient(x, y)

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

  • Загрязняется глобальное пространство имен все переменные которые вы создали в своих сценариях: sum, difference и т.д., теперь находятся в глобальном объекте window. И если вы попытаетесь использовать другую переменную с именем sum, вызываемую в другом файле, то будет трудно разобраться, какое значение будет использоваться в текущем сценарии, поскольку все они будут использовать одну и ту же глобальную переменную window.sum. Единственный способ сделать переменную приватной, это поместить ее в область действия функции. Однако при этом может возникнуть конфликт, между значением x атрибута id элемента DOM и переменной var x
  • Усложняется управление зависимостями сценарии должны загружаться в заданном порядке следования сверху вниз, чтобы корректно обеспечить доступность всех переменных в нужное время. Сохранение сценариев в виде разных файлов создает иллюзию разделения, но по сути это то же самое, что сохранение всего Javascript кода вместе в inline теге <script>

Стандарт ECMAScript 2015 поддерживает использование модулей JavaScript.

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

Модули

Ключевые слова importи export используются для работы с модулями в JavaScript:

  • import применяется для чтения кода, экспортируемого из другого модуля
  • export применяется для предоставления кода другим модулям

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

functions.jsexport function sum(x, y) {
return x + y
}
export function difference(x, y) {
return x - y
}
export function product(x, y) {
return x * y
}
export function quotient(x, y) {
return x / y
}

Теперь в верхней части файла script.js, нам необходимо использовать ключевое слово import для извлечения (импорта) кода функций из модуля functions.js.

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

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

script.jsimport { sum, difference, product, quotient } from './functions.js'
const x = 10
const y = 5
document.getElementById('x').textContent = x
document.getElementById('y').textContent = y
document.getElementById('addition').textContent = sum(x, y)
document.getElementById('subtraction').textContent = difference(x, y)
document.getElementById('multiplication').textContent = product(x, y)
document.getElementById('division').textContent = quotient(x, y)

Чтобы этот код загружался в браузере как модуль, а не как обычный скрипт, добавьте в файл index.html к тегу script атрибут type="module". Любой код, который использует инструкции import или export должен содержать указанный атрибут при подключении соответствующего файла модуля:

index.html<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JavaScript Modules</title>
    </head>
    <body>
    <h1>Answers</h1>
    <h2><strong id="x"></strong> and <strong id="y"></strong></h2>
    <h3>Addition</h3>
    <p id="addition"></p>
    <h3>Subtraction</h3>
    <p id="subtraction"></p>
    <h3>Multiplication</h3>
    <p id="multiplication"></p>
    <h3>Division</h3>
    <p id="division"></p>
    <script type="module" src="functions.js"></script>
    <script type="module" src="script.js"></script>
    </body>
</html>

Теперь вы сможете перезагрузить обновленную страницу, и ваш веб-сайт будет использовать нативный механизм модулей Javascript. Поддержка браузерами этой новой возможности достаточно высока, используйте сервис caniuse, чтобы узнать какие браузеры ее поддерживают. Модули должны использоваться на серверной стороне, которая настраивается локально на компьютере с помощью http-сервера или в сети Интернет с помощью хостинг-провайдера.

Модули отличаются от обычных скриптов несколькими существенными особенностями:

  • Модули ничего не добавляют в global глобальную область видимости или в объект window
  • Модули всегда выполняются в строгом режиме strict mode
  • Загрузка одного и того же модуля дважды в один и тот же файл не будет иметь никакого эффекта, поскольку модули выполняются только один раз
  • Работа с модулями требует серверной среды выполнения кода

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

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

Как уже говорилось ранее, использование синтаксиса export позволяет выборочно импортировать именованные инструкции кода, которые экспортируются из модуля по имени. Например, рассмотрим следующую упрощенную версию файла functions.js:

functions.jsexport function sum(x, y) {
return x + y;
}
export function difference(x, y) {
return x - y;
}

Этот код позволяет импортировать функции sum и difference по их имени, используя фигурные скобки:

script.jsimport { sum, difference } from "./functions.js";
const x = 10;
const y = 5;
document.getElementById("addition").textContent = sum(x, y);
document.getElementById("subtraction").textContent = difference(x, y);

Псевдонимы

Можно использовать синтаксис псевдонимов для переименования импортируемых функций. Эта возможность позволяет избежать конфликтов имен в импортирующем файле. В следующем примере функция sum будет переименована в add, difference в subtract. Вызов функции add() эквивалентен вызову функции sum():

script.jsimport { sum as add, difference as subtract } from "./functions.js";
const x = 10;
const y = 5;
document.getElementById("addition").textContent = add(x, y);
document.getElementById("subtraction").textContent = subtract(x, y);

Объекты

Используя * синтаксис, вы можете импортировать содержимое всего модуля в составе одного объекта. В этом случае функции sum и difference будут доступны как методы объекта mathFunctions:

script.jsimport * as mathFunctions from "./functions.js";
document.getElementById("addition").textContent = mathFunctions.sum(1, 2); // 3
document.getElementById("subtraction").textContent = mathFunctions.difference(10, 3); // 7

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

// Примитивные значения
export const number = 100
export const string = 'string'
export const undef = undefined
export const empty = null
export const obj = { name: 'Homer' }
export const array = ['Bart', 'Lisa', 'Maggie']
// Функциональное выражение
export const sum = (x, y) => x + y
// Определение функции
export function difference(x, y) {
    return x - y
}
// Асинхронная функция
export async function getBooks() {}
// Класс
export class Book {
    constructor(name, author) {
    this.name = name
    this.author = author
    }
}
// Экземпляр класса
export const book = new Book('Lord of the Rings', 'J. R. R. Tolkien')

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

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

Перепишем код файла functions.js в следующем виде:

functions.jsexport default function sum(x, y) {
return x + y
}

В файле script.js импортируем функцию sum по умолчанию, как это показано в коде ниже, в переменной sum будет объект с экспортированным функциями:

script.jsimport sum from "./functions.js";
document.getElementById("addition").textContent = sum(1, 2); // 3

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

script.jsimport difference from './functions.js'
difference(1, 2) // 3

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

export default {
name: 'Lord of the Rings',
author: 'J. R. R. Tolkien',
}

Импортировать объект book можно следующим образом:

import book from './functions.js'

Точно так же в следующем примере демонстрируется экспорт по умолчанию анонимной стрелочной функции:

export default () => 'This function is anonymous'

Функция импортируется из модуля следующим образом:

import anonymousFunction from './functions.js'

Именованный экспорт и экспорт по умолчанию можно использовать совместно друг с другом, как в модуле из примера ниже, который экспортирует два именованных значения и одно значение (функцию) по умолчанию:

export const length = 10
export const width = 5
export default function perimeter(x, y) {
    return 2 * (x + y)
}

Импортируются эти переменные и функция следующим образом:

import calculatePerimeter, { length, width } from './functions.js'
calculatePerimeter(length, width) // 30

Инициализация модуля без импорта его частей

Используется, когда необходимо выполнить импорт модуля для выполнения кода внутри него, но не импортировать какую-либо его часть:

import './modulePath/index.js';
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг