From 1c358d0a2b8e96ab40f77fc2194e0a487b7a2ea5 Mon Sep 17 00:00:00 2001 From: Andrii Hrushetskyi Date: Mon, 17 Feb 2025 21:16:37 +0100 Subject: [PATCH 1/2] fixed typos and simplified explanation **In chapter 01-05-06-iterable** Some of sentences were correct, but they were "unnatural" in Ukrainian and make understanding more difficult. --- 1-js/05-data-types/06-iterable/article.md | 81 ++++++++++++----------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/1-js/05-data-types/06-iterable/article.md b/1-js/05-data-types/06-iterable/article.md index fb0f4ae2f..a1126fb79 100644 --- a/1-js/05-data-types/06-iterable/article.md +++ b/1-js/05-data-types/06-iterable/article.md @@ -1,16 +1,16 @@ # Ітеративні об’єкти -*Ітеративні* об’єкти є узагальненням масивів. Це концепція, яка дозволяє нам зробити будь-який об’єкт придатним для використання в циклі `for..of`. +*Ітеративні* (від англ. iterable) об’єкти є узагальненням масивів. Це концепція, яка дозволяє нам використовувати будь-який об’єкт в циклі `for..of`. -Звичайно, по масивах можна ітеруватися. Але є багато інших вбудованих об’єктів, які також можна ітерувати. Наприклад, рядки також можна ітерувати. +Звісно ж, самі масиви є ітеративними. Але є й багато інших вбудованих об’єктів, які також можна перебирати (ітерувати). Як от до прикладу рядки. -Якщо об’єкт технічно не є масивом, а представляє колекцію (list, set) чогось, то `for..of` -- чудовий синтаксис для його обходу, тому подивімось, як змусити його працювати. +Якщо об’єкт не є масивом, але по своїй суті є колекцією (списком, набором) чогось, то зручно використовувати цикл `for..of` для його ітерування (перебирання). Тому давай подивимось як це можна зробити. ## Symbol.iterator -Ми можемо легко зрозуміти концепцію ітеративних об’єктів, зробивши її власноруч. +Нам буде легко зрозуміти концепцію ітеративних об’єктів, якщо зробимо такий об'єкт власноруч. Наприклад, у нас є об’єкт, який не є масивом, але виглядає придатним для `for..of`. @@ -28,12 +28,12 @@ let range = { Щоб зробити об’єкт `range` ітерабельним (і таким чином дозволити `for..of` працювати), нам потрібно додати метод до об’єкта з назвою `Symbol.iterator` (спеціальний вбудований символ саме для цього). -1. Коли `for..of` запускається, він викликає цей метод один раз (або викидає помилку, якщо цей метод не знайдено). Метод повинен повернути *iterator* -- об’єкт з методом `next`. +1. Коли `for..of` запускається, він викликає цей метод один раз (або викидає помилку, якщо не може знайти цей метод). Метод повинен повернути *iterator* -- об’єкт з методом `next`. 2. Далі `for..of` працює *лише з поверненим об’єктом*. -3. Коли `for..of` хоче отримати наступне значення, він викликає `next()` на цьому об’єкті. +3. Коли `for..of` хоче отримати наступне значення, він викликає `next()` з цього об’єкта. 4. Результат `next()` повинен мати вигляд `{done: Boolean, value: any}`, де `done=true` означає, що ітерація завершена, інакше `value` -- це наступне значення. -Ось повна реалізація об’єкту `range` із зауваженнями: +Ось повна реалізація об’єкту `range` із поясненнями: ```js run let range = { @@ -66,12 +66,12 @@ for (let num of range) { } ``` -Будь ласка, зверніть увагу на основну особливість ітеративних об’єктів: розділення проблем. +Будь ласка, зверніть увагу на основну особливість ітеративних об’єктів: розділення відповідальностей. - Сам `range` не має методу `next()`. - Натомість інший об’єкт, так званий "ітератор", створюється за допомогою виклику `range[Symbol.iterator]()`, а його `next()` генерує значення для ітерації. -Отже, об’єкт, що ітерує відокремлений від об’єкта, який він ітерує. +Отже, об’єкт, що ітерує, відокремлений від об’єкта, який він ітерує. Технічно, ми можемо об’єднати їх і використовувати `range` в якості ітератора, щоб зробити код простішим. @@ -101,24 +101,25 @@ for (let num of range) { } ``` -Тепер `range[Symbol.iterator]()` повертає сам об’єкт `range`: він має необхідний `next()` метод і пам’ятає поточну ітерацію прогресу в `this.current`. Коротше? Так. А іноді це також добре. +Тепер `range[Symbol.iterator]()` повертає сам об’єкт `range`: він має необхідний `next()` метод і пам’ятає поточну ітерацію прогресу в `this.current`. Коротше? Так. А іноді це ще й добре. -Недоліком є те, що тепер неможливо мати два `for..of` цикли паралельно для проходження через об’єкт: вони будуть ділити ітераційний стан, тому що є тільки один ітератор -- сам об’єкт. Але два паралельних for-of це рідкісний випадок, навіть у асинхронізованих сценаріях. +Недоліком є те, що тепер неможливо мати два `for..of` цикли паралельно для проходження через об’єкт: +в них буде спільний ітераційний стан, бо тепер є тільки один ітератор -- сам об’єкт. Але два паралельних for-of це рідкісний випадок, навіть у асинхронізованих сценаріях. -```smart header="Infinite iterators" -Також можливі нескінченні ітератори. Наприклад, `range` стає нескінченним для `range.to = Infinity`. Або ми можемо зробити ітерований об’єкт, який генерує нескінченну послідовність псевдорандомних чисел. Це також може бути корисним. +```smart header="Нескінченні оператори" +Також можливі нескінченні ітератори (англ. infinite iterators). Наприклад, `range` стає нескінченним для `range.to = Infinity`. Або ми можемо зробити ітеровуваний об’єкт, який генерує нескінченну послідовність псевдовипадкових чисел. Це також може бути корисним. Немає обмежень на `next`, він може повертати все більше і більше значень, це нормально. -Звичайно, `for..of` цикли через такий об’єкт буде нескінченним. Але ми завжди можемо зупинити його за допомогою `break`. +Звичайно, `for..of` цикл через такий об’єкт буде нескінченним. Але ми завжди можемо зупинити його за допомогою `break`. ``` -## Рядок є ітерованим +## Рядок є ітеровуваним -Масиви та рядки найбільш широко використовуються вбудовані ітератори. +Масиви та рядки є найбільш широко використовуваними вбудованими ітераторами. -Для рядка, `for..of` цикл проходить по символам: +Для рядка `for..of` цикл проходить по символах: ```js run for (let char of "test") { @@ -127,7 +128,7 @@ for (let char of "test") { } ``` -І це правильно працює з сурогатними парами! +І це правильно працює з [сурогатними парами](https://learn.microsoft.com/en-us/windows/win32/intl/surrogates-and-supplementary-characters)! ```js run let str = '𝒳😂'; @@ -140,7 +141,7 @@ for (let char of str) { Для глибшого розуміння, подивімось, як явно використовувати ітератор. -Ми будемо ітерувати рядок точно так само, як для `for..of`, але з прямими викликами. Цей код створює ітератор рядка і отримує значення від нього "вручну": +Ми будемо ітерувати рядок точно так само, як для `for..of`, але вручну, прямими викликами. Цей код створює ітератор рядка і отримує значення від нього "вручну": ```js run let str = "Привіт"; @@ -161,21 +162,21 @@ while (true) { Це рідко потрібно, але дає нам більше контролю над процесом, ніж `for ..of`. Наприклад, ми можемо розділити процес ітерації: трохи ітерувати, а потім зупинитися, зробити щось інше, а потім відновити пізніше. -## Ітеровані об’єкти та псевдомасиви [#array-like] +## ітеровувані об’єкти та псевдомасиви [#array-like] -Ці два офіційних терміни виглядають подібними, але дуже різні. Будь ласка, переконайтеся, що ви добре розумієте їх, щоб уникнути плутанини. +Ці два офіційних терміни виглядають подібними, але дуже різні. Будь ласка, переконайтеся, що ви добре розумієте їх, щоб уникнути плутанини: -- *Ітеровані* -- це об’єкти, які реалізують метод `Symbol.iterator`, як описано вище. +- *Ітератори* -- це об’єкти, які реалізують метод `Symbol.iterator`, як описано вище. - *Псевдомасиви* -- це об’єкти, які мають індекси та `length`, тому вони виглядають як масиви. -Коли ми використовуємо JavaScript для практичних завдань у браузері або будь-якому іншому середовищі, ми можемо зустріти об’єкти, які є ітерованими або масивами, або обома. -Наприклад, рядки є ітерованими об’єктами (`for..of` працює на них) та псевдомасивами (у них є числові індекси та `length`). +Коли ми використовуємо JavaScript для практичних завдань у браузері або будь-якому іншому середовищі, ми можемо зустріти об’єкти, які є ітеровуваними об'єктами або псевдомасивами, або й і тим, і тим одночасно. +Наприклад, рядки є ітеровуваними об’єктами (`for..of` працює на них) та псевдомасивами (у них є числові індекси та `length`) одночасно. -Але ітерований об’єкт може не бути масивом. І навпаки, псевдомасив може бути не ітерованим об’єктом. +Але ітеровуваний об’єкт може не бути масивом. І навпаки, псевдомасив може бути не ітеровуваним об’єктом. -Наприклад, `range` у прикладі вище є ітерованим об’єктом, але не масивом, тому що він не має індексованих властивостей та `length`. +Наприклад, `range` у прикладі вище є ітеровуваним об’єктом, але не масивом, тому що він не має індексованих властивостей та `length`. -І ось об’єкт, який є псевдомасивом, але не ітерованим об’єктом: +І ось об’єкт, який є псевдомасивом, але не ітеровуваним об’єктом: ```js run let arrayLike = { // має індекси та length => псевдомасив @@ -190,11 +191,11 @@ for (let item of arrayLike) {} */!* ``` -Обидва, ітерований об’єкт та псевдомасив, як правило є *не масивами*, вони не мають `push`,` pop` та ін. Це досить незручно, якщо у нас є такий об’єкт і ми хочемо працювати з ним як з масивом. Наприклад, ми хотіли б працювати з `angy` за допомогою методів масиву. Як цього досягти? +Обидва, ітеровуваний об’єкт та псевдомасив, як правило є *не масивами*, вони не мають `push`,` pop` та ін. Це досить незручно якщо у нас є такий об’єкт і ми хочемо працювати з ним як з масивом. Наприклад, ми хотіли б працювати з `range` за допомогою методів масиву. Як цього досягти? ## Array.from -Існує універсальний метод [Array.from](mdn:js/Array/from), який приймає ітерований об’єкт або псевдомасив і робить з нього "справжній" масив. Тоді ми можемо викликати на ньому методи масиву. +Існує універсальний метод [Array.from](mdn:js/Array/from), який приймає ітеровуваний об’єкт або псевдомасив і робить з нього "справжній" масив. Тоді ми можемо викликати на ньому методи масиву. Наприклад: @@ -211,14 +212,14 @@ let arr = Array.from(arrayLike); // (*) alert(arr.pop()); // Світ (метод працює) ``` -`Array.from` у рядку `(*)` бере об’єкт, перевіряє його на ітерабельність або те, що це псевдомасив, потім створює новий масив і копіює до нього всі елементи. +`Array.from` у рядку `(*)` бере об’єкт, перевіряє чи він ітерабельний і чи це псевдомасив, потім створює новий масив і копіює до нього всі елементи. -Те ж саме відбувається і з ітерованим об’єктом: +Те ж саме відбувається і з ітеровуваним об’єктом: ```js run -// припустимо, що діапазон взятий з наведеного вище прикладу +// range взятий з наведеного вище прикладу let arr = Array.from(range); -alert(arr); // 1,2,3,4,5 (array toString conversion works) +alert(arr); // 1,2,3,4,5 (перетворення масива з допомогою toString працює) ``` Повний синтаксис для `Array.from` також дозволяє нам надати додаткову функцію "трансформації": @@ -268,7 +269,7 @@ alert(chars); ``` ... Але значно коротше. -До речі, ми можемо створити `slice`, якій підтримує сурогатні пари: +До речі, ми можемо створити `slice`, який підтримує сурогатні пари: ```js run function slice(str, start, end) { return Array.from(str).slice(start, end).join(''); @@ -285,18 +286,18 @@ alert( str.slice(1, 3) ); // сміття (дві частини різних с ## Підсумки -Об’єкти, які можна використовуватися у `for..of`, називаються *ітерованими*. +Об’єкти, які можна використовувати у `for..of`, називаються *ітеровуваними*. -- Технічно ітеровані об’єкти повинні реалізовувати метод з назвою `Symbol.iterator`. +- Технічно ітеровувані об’єкти повинні реалізовувати метод з назвою `Symbol.iterator`. - Результат `obj[Symbol.iterator]()` називається *ітератором*. Він забезпечує подальший процес ітерації. - Ітератор повинен мати метод з назвою `next()`, який повертає об’єкт `{done: Boolean, value: any}`, де `done: true` означає кінець процесу ітерації, інакше `value` є наступним значенням. -- Метод `Symbol.iterator` автоматично викликається `for..of`, але ми також можемо це зробити безпосередньо. -- Вбудовані ітеровані об’єкти, такі як рядки або масиви, також реалізують `Symbol.iterator`. +- Метод `Symbol.iterator` автоматично викликається `for..of`, але ми також можемо це зробити вручну. +- Вбудовані ітеровувані об’єкти, такі як рядки або масиви, також реалізують `Symbol.iterator`. - Рядковий ітератор знає про сурогатні пари. Об’єкти, які мають індексовані властивості та `length`, називаються *псевдомасивами*. Такі об’єкти також можуть мати інші властивості та методи, але не мають вбудованих методів масивів. -Якщо ми заглянемо в специфікацію -- ми побачимо, що більшість вбудованих методів припускають, що вони працюють з ітерованими об’єктами або псевдомасивами замість "реальних" масивів, тому що це більш абстрактно. +Якщо ми заглянемо в специфікацію -- ми побачимо, що більшість вбудованих методів припускають, що вони працюють з ітеровуваними об’єктами або псевдомасивами замість "реальних" масивів, тому що це більш абстрактно. -`Array.from(obj[, mapFn, thisArg])` створює справжній `Array` з ітерованого об’єкту або псевдомасиву `obj`, і тоді ми можемо використовувати на ньому методи масиву. Необов’язкові аргументи `mapFn` та` thisArg` дозволяють нам застосовувати функції до кожного елемента. +`Array.from(obj[, mapFn, thisArg])` створює справжній `Array` з ітеровуваного об’єкту або псевдомасиву `obj`, і тоді ми можемо використовувати на ньому методи масиву. Необов’язкові аргументи `mapFn` та` thisArg` дозволяють нам застосовувати функції до кожного елемента. From b1763f30ffcb3256c43765c37db1484707704a4e Mon Sep 17 00:00:00 2001 From: Andrii Hrushetskyi Date: Mon, 17 Feb 2025 21:19:07 +0100 Subject: [PATCH 2/2] fixed typos in 01-05-06-iterable **In chapter 01-05-06-iterable** Some of sentences were correct, but they were "unnatural" in Ukrainian and make understanding more difficult. --- 1-js/05-data-types/06-iterable/article.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/1-js/05-data-types/06-iterable/article.md b/1-js/05-data-types/06-iterable/article.md index a1126fb79..ea0fa9ee2 100644 --- a/1-js/05-data-types/06-iterable/article.md +++ b/1-js/05-data-types/06-iterable/article.md @@ -1,16 +1,16 @@ -# Ітеративні об’єкти +# Ітеровувані об’єкти -*Ітеративні* (від англ. iterable) об’єкти є узагальненням масивів. Це концепція, яка дозволяє нам використовувати будь-який об’єкт в циклі `for..of`. +*Ітеровувані* (від англ. iterable) об’єкти є узагальненням масивів. Це концепція, яка дозволяє нам використовувати будь-який об’єкт в циклі `for..of`. -Звісно ж, самі масиви є ітеративними. Але є й багато інших вбудованих об’єктів, які також можна перебирати (ітерувати). Як от до прикладу рядки. +Звісно ж, самі масиви є ітеровуваними. Але є й багато інших вбудованих об’єктів, які також можна перебирати (ітерувати). Як от до прикладу рядки. Якщо об’єкт не є масивом, але по своїй суті є колекцією (списком, набором) чогось, то зручно використовувати цикл `for..of` для його ітерування (перебирання). Тому давай подивимось як це можна зробити. ## Symbol.iterator -Нам буде легко зрозуміти концепцію ітеративних об’єктів, якщо зробимо такий об'єкт власноруч. +Нам буде легко зрозуміти концепцію ітеровуваних об’єктів, якщо зробимо такий об'єкт власноруч. Наприклад, у нас є об’єкт, який не є масивом, але виглядає придатним для `for..of`. @@ -66,7 +66,7 @@ for (let num of range) { } ``` -Будь ласка, зверніть увагу на основну особливість ітеративних об’єктів: розділення відповідальностей. +Будь ласка, зверніть увагу на основну особливість ітеровуваних об’єктів: розділення відповідальностей. - Сам `range` не має методу `next()`. - Натомість інший об’єкт, так званий "ітератор", створюється за допомогою виклику `range[Symbol.iterator]()`, а його `next()` генерує значення для ітерації.