diff --git a/manuscript/13-Modules.md b/manuscript/13-Modules.md index c30762c..8da1718 100644 --- a/manuscript/13-Modules.md +++ b/manuscript/13-Modules.md @@ -1,6 +1,6 @@ # Інкапсуляція коду за допомогою модулів -Одним з найбільш схильних до помилок і заплутаних аспектів JavaScript вже давно є shared everything-підхід до завантаження коду. В той час як інші мови мають такі поняття як пакети, JavaScript відстав і все, що визначається в кожному файлі поділяє єдину глобальну область видимості. Тоді, коли веб-додатки стали більш складними, а частота використання JavaScript зросла, shared everything-підхід почав виявляти проблеми з конфліктами імен, проблеми безпеки та багато іншого. Однією з цілей ECMAScript 6 було вирішення цієї проблеми і наведення порядку в додатках JavaScript. Ось тут і з’являються модулі. +Одним з найбільш схильних до помилок і заплутаних аспектів JavaScript вже давно є shared everything-підхід до завантаження коду. В той час як інші мови мають такі поняття як пакети, JavaScript відстав і все, що визначається в кожному файлі, поділяє єдину глобальну область видимості. Тоді, коли веб-додатки стали більш складними, а частота використання JavaScript зросла, shared everything-підхід почав виявляти проблеми з конфліктами імен, проблеми безпеки та багато іншого. Однією з цілей ECMAScript 6 було вирішення цієї проблеми і наведення порядку в додатках JavaScript. Ось тут і з’являються модулі. ## Що таке модулі? @@ -27,7 +27,7 @@ export const magicNumber = 7; // експортуємо функцію export function sum(num1, num2) { -   return num1 + num1; +   return num1 + num2; } // експортуємо клас @@ -68,7 +68,7 @@ import { identifier1, identifier2 } from "./example.js"; I> Список зв’язувань для імпорту виглядає подібно до деструктурованого об’єкту, але не є ним. -За імпортування зв'язувань з модуля, воно поводиться так, ніби його було визначено за допомогою `const`. Це означає, що ви не можете визначити іншу змінну з тим же ім'ям (в тому числі імпорту іншого зв'язування з тим же ім'ям), використовуйте ідентифікатор до оголошення `import` або змініть його значення. +За імпортування зв'язувань з модуля, воно поводиться так, ніби його було визначено за допомогою `const`. Це означає, що ви не можете визначити іншу змінну з тим же ім'ям (в тому числі імпорт іншого зв'язування з тим же ім'ям), використовуйте ідентифікатор до оголошення `import` або змініть його значення. ### Імпортування одиничного зв'язування @@ -85,7 +85,7 @@ sum = 1;        // помилка Незважаючи на те, що `example.js` експортує більше, ніж просто одну функцію, цей приклад імпортує тільки функцію `sum()`. При спробі присвоїти нове значення `sum`, результатом буде помилка, оскільки ви не можете перевизначити імпортовані зв'язування. -W> Переконайтеся в тому, щоб включити `/`, `./`, чи `../` на початку файлу який ви імпортуєте для кращої сумісності в різних браузерах і Node.js. +W> Переконайтеся в тому, щоб включити `/`, `./`, чи `../` на початку файлу, який ви імпортуєте для кращої сумісності в різних браузерах і Node.js. ### Імпортування кількох зв’язувань @@ -134,7 +134,7 @@ if (flag) { } ``` -Вираз `export` всередині оператору `if`, не дозволяється. Експорт не може бути умовним або зроблений динамічно будь-яким чином. Однією з причин цього синтаксису модуля, є можливість дозволити рушію JavaScript визначити, що буде експортовано статично. Таким чином, ви можете використовувати `export` тільки на найвищому рівні модуля. +Вираз `export` всередині оператору `if` не дозволяється. Експорт не може бути умовним або зроблений динамічно будь-яким чином. Однією з причин цього синтаксису модуля, є можливість дозволити рушію JavaScript визначити, що буде експортовано статично. Таким чином, ви можете використовувати `export` тільки на найвищому рівні модуля. Крім того, ви не можете використовувати `import` всередині виразу; ви можете використовувати його тільки на найвищому рівні. Це означає, що цей код також спричинить синтаксичну помилку: @@ -144,11 +144,11 @@ function tryImport() { } ``` -Ви не можете динамічно імпортувати зв'язування з тієї ж причини з якої ви не можете динамічно їх експортувати. Ключові слова `export` та `import` створені для того, щоб бути статичними, тому інструменти, такі як текстові редактори можуть легко сказати, яка інформація доступна з модуля. +Ви не можете динамічно імпортувати зв'язування з тієї ж причини, з якої ви не можете динамічно їх експортувати. Ключові слова `export` та `import` створені для того, щоб бути статичними, тому інструменти, такі як текстові редактори, можуть легко сказати, яка інформація доступна з модуля. ### Тонкий момент в імпортуванні зв'язування -В ECMAScript 6 вираз `import` створює доступні лише для читання зв'язування до змінних, функцій і класів, а не просто посилання на оригінальні зв'язування як звичайні змінні. Навіть незважаючи на те, що модуль який імпортує зв'язування не може змінити його значення, модуль, який експортує цей ідентифікатор може. Наприклад, припустимо, що ви хочете використовувати цей модуль: +В ECMAScript 6 вираз `import` створює доступні лише для читання зв'язування до змінних, функцій і класів, а не просто посилання на оригінальні зв'язування як звичайні змінні. Навіть незважаючи на те, що модуль, який імпортує зв'язування, не може змінити його значення, модуль, який експортує цей ідентифікатор, може. Наприклад, припустимо, що ви хочете використовувати цей модуль: ```js export var name = "Nicholas"; @@ -169,13 +169,13 @@ console.log(name);       // "Greg" name = "Nicholas";       // помилка ``` -Виклик `setName("Greg")` повертається до модуля, з якого експортувалась `setName()` і виконується там, встановлюючи `name` в `"Greg"`. Зверніть увагу, ця зміна автоматично відображається на імпортованому зв'язуванні `name`. Це тому, що `name` є локальним ім'ям для ідентифікатора `name`, який експортується. `name` використане в коді вище і `name`, використане в модулі з якого було імпортоване — це не одне й те ж саме. +Виклик `setName("Greg")` повертається до модуля, з якого експортувалась `setName()` і виконується там, встановлюючи `name` в `"Greg"`. Зверніть увагу, ця зміна автоматично відображається на імпортованому зв'язуванні `name`. Це тому, що `name` є локальним ім'ям для ідентифікатора `name`, який експортується. `name`, використане в коді вище і `name`, використане в модулі, з якого було імпортоване — це не одне й те ж саме. ## Перейменування імпортів і експортів -Іноді, ви можете не захотіти використовувати оригінальне ім'я змінної, функції або класу яку ви імпортували з модуля. На щастя, ви можете змінити назву експорту як при експорті, так і при імпорті. +Іноді ви можете не захотіти використовувати оригінальне ім'я змінної, функції або класу, які ви імпортували з модуля. На щастя, ви можете змінити назву експорту як при експорті, так і при імпорті. -У першому випадку, припустимо, що у вас є функція, яку ви хотіли б експортувати з іншим ім'ям. Ви можете використовувати ключове слово `as`, щоб вказати ім'я з яким функція повинна бути відома за межами модуля: +У першому випадку, припустимо, що у вас є функція, яку ви хотіли б експортувати з іншим ім'ям. Ви можете використовувати ключове слово `as`, щоб вказати ім'я, з яким функція повинна бути відома за межами модуля: ```js function sum(num1, num2) { @@ -185,7 +185,7 @@ function sum(num1, num2) { export { sum as add }; ``` -Тут, функція `sum()` (`sum` — це *локальне ім’я*) експортована як `add()` (`add` — це *експортоване ім’я*). Це означає, що коли інший модуль хоче імпортувати цю функцію, він має використовувати ім'я `add`: +Тут функція `sum()` (`sum` — це *локальне ім’я*) експортована як `add()` (`add` — це *експортоване ім’я*). Це означає, що коли інший модуль хоче імпортувати цю функцію, він має використовувати ім'я `add`: ```js import { add } from "./example.js"; @@ -199,7 +199,7 @@ console.log(typeof add);            // "undefined" console.log(sum(1, 2));             // 3 ``` -Цей код імпортує функцію `add()` використовуючи *імпортоване ім’я* та перейменовує її на `sum()` (локальне ім’я). Це означає, що в цьому модулі більше немає ідентифікатора з ім’ям `add`. +Цей код імпортує функцію `add()`, використовуючи *імпортоване ім’я*, та перейменовує її на `sum()` (локальне ім’я). Це означає, що в цьому модулі більше немає ідентифікатора з ім’ям `add`. ## Значення за замовчуванням в модулях @@ -240,7 +240,7 @@ function sum(num1, num2) { export { sum as default }; ``` -Ідентифікатор `default` має особливе значення в перейменуванні експорту і вказує, що значення має бути значенням за замовчуванням для модуля. Оскільки `default` — це ключове слово в JavaScript, воно не може бути використане для змінної, функції або ім’я класу (але воно може бути використане в якості ім’я властивості). Таким чином, використання `default` для перейменування експорту є окремим випадком, щоб створити узгодженість з тим, як визначається структура експорту не за замовчуванням. Цей синтаксис корисний, якщо ви хочете використовувати один екземпляр `export` щоб визначити відразу кілька експортів, в тому числі за замовчуванням. +Ідентифікатор `default` має особливе значення в перейменуванні експорту і вказує, що значення має бути значенням за замовчуванням для модуля. Оскільки `default` — це ключове слово в JavaScript, воно не може бути використане для змінної, функції або ім’я класу (але воно може бути використане в якості ім’я властивості). Таким чином, використання `default` для перейменування експорту є окремим випадком, щоб створити узгодженість з тим, як визначається структура експорту не за замовчуванням. Цей синтаксис корисний, якщо ви хочете використовувати один екземпляр `export`, щоб визначити відразу кілька експортів, в тому числі за замовчуванням. ### Імпорт значень за замовчуванням @@ -253,7 +253,7 @@ import sum from "./example.js"; console.log(sum(1, 2));     // 3 ``` -Цей оператор імпорту імпортує значення за замовчуванням з модуля `example.js`. Зверніть увагу, що фігурні дужки не використовуються, на відміну від того, що ви бачили в імпорті не за замовчуванням. Локальне ім’я `sum` використовується для позначення будь-якої функції за замовчуванням яку експортує модуль. Цей синтаксис є найчистішим, і творці ECMAScript 6 очікують, що він буде домінуючою формою імпорту в Інтернеті, що дозволяє вам використовувати вже існуючий об'єкт. +Цей оператор імпорту імпортує значення за замовчуванням з модуля `example.js`. Зверніть увагу, що фігурні дужки не використовуються, на відміну від того, що ви бачили в імпорті не за замовчуванням. Локальне ім’я `sum` використовується для позначення будь-якої функції за замовчуванням, яку експортує модуль. Цей синтаксис є найчистішим, і творці ECMAScript 6 очікують, що він буде домінуючою формою імпорту в Інтернеті, що дозволяє вам використовувати вже існуючий об'єкт. Для модулів, які експортують, як значення за замовчуванням, так і один або кілька зв'язувань не за замовчуванням, ви можете імпортувати всі експортовані зв'язування за допомогою одного оператора. Наприклад, припустимо, що у вас є такий модуль: @@ -274,7 +274,7 @@ console.log(sum(1, 2));     // 3 console.log(color);         // "red" ``` -Кома відділяє локальне ім'я за замовчуванням від імен не за замовчуванням, які також оточені фігурними дужками. Майте на увазі, що за значення за замовчуванням повинне йти перед іменами не за замовчуванням в виразі `import`. +Кома відділяє локальне ім'я за замовчуванням від імен не за замовчуванням, які також оточені фігурними дужками. Майте на увазі, що значення за замовчуванням повинне йти перед іменами не за замовчуванням в виразі `import`. Як і при експорті за замовчуванням, ви можете імпортувати значення за замовчуванням також з синтаксисом перейменування: @@ -286,11 +286,11 @@ console.log(sum(1, 2));     // 3 console.log(color);         // "red" ``` -У цьому коді, експорт за замовчуванням (`default`) перейменовується в `sum` і додатковий експорт `color`  також імпортується. Цей приклад еквівалентний попередньому прикладу. +У цьому коді експорт за замовчуванням (`default`) перейменовується в `sum` і додатковий експорт `color`  також імпортується. Цей приклад еквівалентний попередньому прикладу. ## Переекспортування зв’язувань -Може статись так, що вам потрібно буде переекспортувати щось, що ваш модуль імпортував (наприклад, якщо ви створюєте бібліотеку з кількох невеликих модулів). Ви можете зробити це, використовуючи шаблони вже розглянуті в цьому розділі, такі як: +Може статись так, що вам потрібно буде переекспортувати щось, що ваш модуль імпортував (наприклад, якщо ви створюєте бібліотеку з кількох невеликих модулів). Ви можете зробити це, використовуючи шаблони, вже розглянуті в цьому розділі, такі як: ```js import { sum } from "./example.js"; @@ -317,13 +317,13 @@ export { sum as add } from "./example.js"; export * from "./example.js"; ``` -При експорті всього ви, разом з усіма експортами, що мають ім’я, експортуєте також і замовчування, які можуть вплинути на те, що ви можете експортувати з вашого модуля. Наприклад, якщо `"example.js"` має експорт за замовчуванням, ви будете не в змозі визначити новий експорт за замовчуванням при використанні цього синтаксису. +При експорті всього ви разом з усіма експортами, що мають ім’я, експортуєте також і замовчування, які можуть вплинути на те, що ви можете експортувати з вашого модуля. Наприклад, якщо `"example.js"` має експорт за замовчуванням, ви будете не в змозі визначити новий експорт за замовчуванням при використанні цього синтаксису. ## Імпортування без зв’язування Деякі модулі можуть нічого не експортувати, а, замість цього, тільки вносити зміни в об'єкти в глобальній області видимості. Навіть якщо змінні верхнього рівня, функції і класи всередині модулів автоматично не потрапляють в глобальну область видимості, це не означає, що модулі не можуть отримати доступ до неї. Загальні визначення вбудованих об'єктів, таких як `Array` і` Object`, доступні всередині модуля і зміни до цих об'єктів будуть віддзеркалені в інших модулях. -Наприклад, припустимо, що ви хочете додати метод до всіх масивів з ім’ям `pushAll()`, ви можете визначити модуль наступним чином: +Наприклад, припустимо, що ви хочете додати до всіх масивів метод з ім’ям `pushAll()`. Ви можете визначити модуль наступним чином: ```js // Код модуля без експортів чи імпортів @@ -356,11 +356,11 @@ I> Імпорти без зв’язування, швидше за все, бу ## Завантаження Модулів -В той час як ECMAScript 6 визначає синтаксис для модулів, він не визначає як їх завантажувати. Це частина складності специфікації, яка повинна буди агностичною до реалізації в різних оточеннях. Замість того щоб намагатися створити єдину специфікацію, яка буде працювати для всіх середовищ JavaScript, ECMAScript 6 визначає тільки синтаксис і тези з механізму завантаження який залишається невизначеним до внутрішньої операції під назвою `HostResolveImportedModule`. Веб-браузерам та Node.js надається можливість вирішити, як реалізувати `HostResolveImportedModule` шляхом, що буде мати сенс для їх середовищ. +В той час як ECMAScript 6 визначає синтаксис для модулів, він не визначає, як їх завантажувати. Це частина складності специфікації, яка повинна буди агностичною до реалізації в різних оточеннях. Замість того, щоб намагатися створити єдину специфікацію, яка буде працювати для всіх середовищ JavaScript, ECMAScript 6 визначає тільки синтаксис і тези з механізму завантаження, який залишається невизначеним до внутрішньої операції під назвою `HostResolveImportedModule`. Веб-браузерам та Node.js надається можливість вирішити, як реалізувати `HostResolveImportedModule` шляхом, що буде мати сенс для їх середовищ. ### Використання модулів в веб-браузерах -Ще до ECMAScript 6, веб-браузери мали кілька способів щоб включати JavaScript у веб-додатки. Цими опціями завантаження скриптів є: +Ще до ECMAScript 6 веб-браузери мали кілька способів щоб включати JavaScript у веб-додатки. Цими опціями завантаження скриптів є: 1. Завантаження файлів коду JavaScript за допомогою елемента `