diff --git a/1-js/06-advanced-functions/02-rest-parameters-spread/article.md b/1-js/06-advanced-functions/02-rest-parameters-spread/article.md index 965b7feea..0a395d68a 100644 --- a/1-js/06-advanced-functions/02-rest-parameters-spread/article.md +++ b/1-js/06-advanced-functions/02-rest-parameters-spread/article.md @@ -6,15 +6,15 @@ - `Math.max(arg1, arg2, ..., argN)` -- повертає найбільший з аргументів. - `Object.assign(dest, src1, ..., srcN)` -- копіює властивості з `src1..N` до `dest`. -- ...і багато ще. +- ...і багато інших. -У цьому розділі ми дізнаємось, як зробити те саме. А також, як передати масиви таким функціям, як параметри. +У цьому розділі ми дізнаємось, як зробити те саме в власній функції. А також, як передати таким функціям в якості параметрів масиви. -## Залишкові параметри `...` +## Залишкові параметри `...` (з англ. rest parameters) -Функцію можна викликати з будь-якою кількістю аргументів, незалежно від того, як вона визначена. +Функцію можна викликати з будь-якою кількістю аргументів, незалежно від того, як вона оголошена. -Як тут: +Як от тут: ```js run function sum(a, b) { return a + b; @@ -23,9 +23,9 @@ function sum(a, b) { alert(sum(1, 2, 3, 4, 5)); ``` -Помилки "надмірних" аргументів у цьому випадку не буде. Але, звичайно, будуть враховані лише перші два, тому результатом у коді вище є `3`. +Помилки із-за "надмірних" аргументів у цьому випадку не буде. Але, звісно ж, враховані будуть лише перші два, тому результатом у коді вище є `3`. -Решту параметрів можна включити до визначення функції за допомогою трьох крапок `...` що передують імені масиву, який їх міститиме. Точки буквально означають "зібрати решту параметрів у масив". +Решту параметрів можна включити до визначення функції за допомогою трьох крапок `...` і після них ім'я масив, в який вони передадуться. Точки буквально означають "зібрати решту параметрів у масив". Наприклад, щоб зібрати всі аргументи в масив `args`: @@ -43,7 +43,7 @@ alert( sumAll(1, 2) ); // 3 alert( sumAll(1, 2, 3) ); // 6 ``` -Ми можемо вибрати перші параметри як змінні, а зібрати у масив лише залишки. +Ми можемо вказати щоб перші параметри отримувались як аргументи, а в масив пішли всі інші. У цьому прикладі перші два аргументи переходять у змінні, а решта -- в масив `titles`: @@ -62,7 +62,7 @@ showName("Юлій", "Цезар", "Консул", "Полководець"); ``` ````warn header="Залишкові параметри повинні бути в кінці" -Залишкові параметри збирають усі залишені аргументи, тому наступне не має сенсу та викликає помилку: +Залишкові параметри збирають усі залишені аргументи, тому такий код не спрацює і викличе помилку: ```js function f(arg1, ...rest, arg2) { // arg2 після ...rest ?! @@ -75,7 +75,7 @@ function f(arg1, ...rest, arg2) { // arg2 після ...rest ?! ## Змінна "arguments" -Існує також спеціальний об’єкт, подібний масиву `arguments` який містить усі аргументи за їх індексом. +Існує також спеціальний псевдомасив, об'єкт `arguments`, який містить усі аргументи з їх індексами. Наприклад: @@ -85,27 +85,27 @@ function showName() { alert(arguments[0]); alert(arguments[1]); - // це повторюване - // for(let arg of arguments) alert(arg); + // він ітеровуваний (перебираваний) + // for(let arg of arguments) alert(arg); працюватиме } -// показує: 2, Julius, Caesar -showName("Julius", "Caesar"); +// показує: 2, Юлій, Цезар +showName("Юлій", "Цезар"); -// показує: 1, Ilya, undefined (жодного другого аргументу) -showName("Ilya"); +// показує: 1, Ілля, undefined (другого аргументу нема) +showName("Ілля"); ``` -За старих часів залишкові параметри не існували в мові, єдиний спосіб отримати всі аргументи функції був за допомогою `arguments`. І він все ще працює, ми можемо знайти його в старому коді. +В стародавні часи такої можливості як залишкові параметри в JavaScript не існувало. Тому єдиним способом отримати всі аргументи функції було за допомогою `arguments`. І він все ще працює, ми можемо знайти його в старому коді. -Але недоліком є те, що хоча `arguments` є одночасно масивом і ітерабельним, це не масив. Він не підтримує методи масиву, тому ми не можемо наприклад викликати `arguments.map(...)`. +Але недоліком є те, що хоч `arguments` є одночасно і псевдомасивом, і ітеровуваним (перебираваним) об'єктом, та все ж це об'єкт, а не масив. Він не підтримує методи масиву, тому ми не можемо наприклад викликати `arguments.map(...)`. -Крім того, він завжди містить усі аргументи. Ми не можемо отримати їх частково, як це було зроблено з параметрами залишку. +Крім того, він завжди містить усі аргументи. Ми не можемо отримати лише частину з них, як це можна робити з допомогою залишкових параметрів. -Тому, коли нам потрібні вбудовані методи, тоді краще використати параметри залишку. +Тому, коли нам потрібні вбудовані методи масивів, тоді краще використати залишкові параметри. -````smart header="Стрілочні функції не мають `\"arguments\"`" - Якщо ми викличемо `arguments` об'єкта із стрілочною функцією, він візьме їх із зовнішньої "звичайної" функції. +````smart header="Стрíлкові функції не мають `\"arguments\"`" + Якщо ми викличемо `arguments` об'єкта всередині стрíлкової функції, він візьме їх із зовнішньої "звичайної" функції. Ось приклад: @@ -118,13 +118,13 @@ function f() { f(1); // 1 ``` -Як ми пам’ятаємо, стрілочні функції не мають власних `this`. Тепер ми знаємо, що у них також немає особливого об'єкту `arguments`. +Як ми пам’ятаємо, стрíлкові функції не мають власних `this`. Тепер ми знаємо, що у них також немає особливого об'єкту `arguments`. ```` -## Синтаксис розширення [#spread-syntax] +## Синтаксис розширення [#spread-syntax] (з англ. spread syntax) -Ми тільки що побачили, як отримати масив зі списку параметрів. +Ми щойно побачили, як отримати масив зі списку параметрів. Але іноді нам потрібно зробити зворотнє. @@ -134,7 +134,7 @@ f(1); // 1 alert( Math.max(3, 5, 1) ); // 5 ``` -Тепер припустимо, що у нас є масив `[3, 5, 1]`. Як нам викликати `Math.max` з цим? +Тепер припустімо, що у нас є масив `[3, 5, 1]`. Як нам викликати `Math.max` з цим? Передати "як є" не вийде, бо `Math.max` очікує список числових аргументів, а не єдиний масив: @@ -146,11 +146,11 @@ alert( Math.max(arr) ); // NaN */!* ``` -І, звісно ж, ми не можемо вручну перераховувати елементи в коді `Math.max(arr[0], arr[1], arr[2])`, тому що ми можемо не знати, скільки їх існує. Під час виконання нашого сценарію їх може бути багато, а може і не бути. І це було б потворно. +І, звісно ж, ми не можемо вручну перераховувати елементи в коді `Math.max(arr[0], arr[1], arr[2])`, тому що ми можемо й не знати, скільки їх існує. Під час виконання нашого сценарію їх може бути багато, а може і не бути. Та й взагалі робити це вручну було б жахливо. Нам допоможе *синтаксис розширення*! Він схожий на параметри залишку, також використовуються `...`, але працює все навпаки. -Коли `...arr` використовується у виклику функції, він "розширює" повторюванний об'єкт `arr` до списку аргументів. +Коли `...arr` використовується в дужках при виклику функції, він "розширює" ітеровуваний об'єкт `arr` до списку аргументів. Для `Math.max`: @@ -189,10 +189,10 @@ let arr2 = [8, 9, 15]; let merged = [0, ...arr, 2, ...arr2]; */!* -alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2) +alert(merged); // 0,3,5,1,2,8,9,15 (0, тоді arr, тоді 2, тоді arr2) ``` -У наведених вище прикладах ми використовували масив для демонстрації синтаксису розширення, але підходить будь-який повторюванний об'єкт. +У наведених вище прикладах для демонстрації синтаксису розширення ми використовували масив, але підходить будь-який ітеровуваний (перебираваний) об'єкт. Наприклад, тут ми використовуємо синтаксис розширення, щоб перетворити рядок у масив символів: @@ -202,32 +202,32 @@ let str = "Hello"; alert( [...str] ); // H,e,l,l,o ``` -Синтаксис розширення внутрішньо використовує ітератори для збору елементів так само, як це робить `for..of`. +Синтаксис розширення під капотом працює з перебираваними об'єктами так само, як це робить `for..of`. -Отже, для рядка, `for..of` повертає символи так само `...str` повертає `"H","e","l","l","o"`. Список символів передається в ініціалізатор масиву `[...str]`. +Отже, для рядка, `for..of` повертає символи й `...str` перетворюється в `"H","e","l","l","o"`. Список символів передається в ініціалізатор масиву `[...str]`. -Для цього конкретного завдання ми також могли б використовувати `Array.from`, тому що він перетворює ітерабельний об'єкт (як рядок) на масив: +Для цього конкретного завдання ми також могли б використовувати `Array.from`, бо він перетворює перебираваний об'єкт (то й же рядок, або щось інше) на масив: ```js run let str = "Hello"; -// Array.from перетворює ітерабельний об'єкт в масив +// Array.from перетворює перебираваний об'єкт в масив alert( Array.from(str) ); // H,e,l,l,o ``` -Результат такий самий як `[...str]`. +Результат такий самий як при `[...str]`. Але між `Array.from(obj)` та `[...obj]` є тонка різниця: -- `Array.from` працює як з масиво-подібними об'єктами, так і з об'єктами, що ітеруються. -- Синтаксис розширення працює тільки з ітераторами. +- `Array.from` працює як з псевдомасивами, так і з перебираваними об'єктами. +- Синтаксис розширення працює тільки з перебираваними об'єктами. -Отже, для завдання перетворити щось на масив `Array.from` буде більш універсальним. +Отже, якщо треба перетворити щось на масив, то `Array.from` буде більш універсальним. ## Створити копію масива/об’єкта -Пригадайте, коли ми говорили `Object.assign()` [в минулому розділі](info:object-copy#cloning-and-merging-object-assign)? +Пам'ятаєте ми раніше говорили про `Object.assign()` [в минулому розділі](info:object-copy#cloning-and-merging-object-assign)? Те ж саме можна зробити і з синтаксисом розширення. @@ -273,23 +273,23 @@ alert(JSON.stringify(obj)); // {"a":1,"b":2,"c":3,"d":4} alert(JSON.stringify(objCopy)); // {"a":1,"b":2,"c":3} ``` -Цей спосіб копіювання об’єкта набагато коротший, ніж `let objCopy = Object.assign({}, obj)` чи для масиву `let arrCopy = Object.assign([], arr)` тому ми вважаємо за краще використовувати його, коли це можливо. +Цей спосіб копіювання об’єкта набагато коротший, ніж `let objCopy = Object.assign({}, obj)` чи для масиву `let arrCopy = Object.assign([], arr)`. Тому ми вважаємо за краще використовувати його, коли це можливо. ## Підсумки -Коли ми бачимо `"..."` у коді це або залишкові параметри, або синтаксис розширення. +Коли ми бачимо `"..."` у коді - це або залишкові параметри, або синтаксис розширення. Існує простий спосіб відрізнити їх: -- Коли `...` находиться в кінці параметрів функції, це "залишкові параметри" і він збирає решту переданих аргументів у масив. +- Коли `...` знаходиться в кінці параметрів функції, це "залишкові параметри" і він збирає решту переданих аргументів у масив. - Коли `...` виникає під час виклику функції чи чогось подібного, це називається "синтаксисом розширення" і розширює масив у список. -Використовуйте паттерни: +Паттерни використання: - Залишкові параметри використовуються для створення функцій, які приймають будь-яку кількість аргументів. - Синтаксис розширення використовується для передачі масиву у функції, які зазвичай вимагають список із багатьох аргументів. Разом вони допомагають легко переміщатися між списком та масивом параметрів. -Усі аргументи виклику функції також доступні в "олдскульному" ітерабельному об’єкті `arguments`. +Усі аргументи виклику функції також доступні в "олдскульному" ітеровуваному об’єкті `arguments`.