You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 1-js/06-advanced-functions/01-recursion/article.md
+10-10Lines changed: 10 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@
8
8
9
9
Рекурсія -- це паттерн, який є корисним у ситуаціях, коли завдання може бути розділено на кілька завдань того ж роду, але простіших. Або коли завдання може бути спрощене до простої дії плюс простіший варіант того ж завдання. Або, як ми побачимо найближчим часом, щоб працювати з певними структурами даних.
10
10
11
-
Коли функція вирішує завдання, у процесі вона може викликати багато інших функцій. Є навіть випадки, коли функція викликає *саму себе*. Коли функція викликає саму себе - це називається *рекурсія*.
11
+
Коли функція вирішує завдання, у процесі вона може викликати багато інших функцій. Є навіть випадки, коли функція викликає *саму себе*. Коли функція викликає саму себе -- це називається *рекурсія*.
12
12
13
13
## Два способи мислення
14
14
@@ -66,7 +66,7 @@ pow(x, n) =
66
66
```
67
67
68
68
1. Якщо `n == 1`, то все просто. Ця гілка називається *базою* рекурсії, оскільки вона негайно дає очевидний результат:`pow(x, 1)` дорівнює `x`.
69
-
2. Інакше ми можемо представити `pow(x, n)` як `x * pow(x, n)`. Що у математиці можна написати <code>x<sup>n</sup>= x * x<sup>n-1</sup></code>. Ця гілка -*крок рекурсії*: ми зводимо задачу до більш простої дії (множеня на `x`) і до більш простої аналогічної задачі (`pow` з меншим `n`). Наступні кроки спрощують задачу все більше і більше, аж доки `n` почне дорівнювати `1`.
69
+
2. Інакше ми можемо представити `pow(x, n)` як `x * pow(x, n)`. Що у математиці можна написати <code>x<sup>n</sup>= x * x<sup>n-1</sup></code>. Ця гілка -- це*крок рекурсії*: ми зводимо задачу до більш простої дії (множеня на `x`) і до більш простої аналогічної задачі (`pow` з меншим `n`). Наступні кроки спрощують задачу все більше і більше, аж доки `n` почне дорівнювати `1`.
70
70
71
71
Ми також можемо сказати, що `pow`*рекурсивно викликає себе* до`n == 1`.
72
72
@@ -80,9 +80,9 @@ pow(x, n) =
80
80
3.`pow(2, 2) = 2 * pow(2, 1)`
81
81
4.`pow(2, 1) = 2`
82
82
83
-
Отже, рекурсію використовують, коли обчислення функції можна звести до її ж більш простого виклику, а той - до ще простішого і так далі, аж доки значення не стане максимально простим (очевидним).
83
+
Отже, рекурсію використовують, коли обчислення функції можна звести до її ж більш простого виклику, а той -- до ще простішого і так далі, аж доки значення не стане максимально простим (очевидним).
84
84
85
-
````smart header="Рекурсійне рішення зазвичай коротше"
85
+
````smart header="Рішення з використанням рекурсії зазвичай коротше"
86
86
Рекурсивне рішення, як правило, коротше за ітераційне.
87
87
88
88
Ми можемо переписати те ж саме, використовуючи умовний оператор `?` замість `if`, щоб зробити `pow(x, n)` більш лаконічним і зберегти легкість читання:
@@ -96,7 +96,7 @@ function pow(x, n) {
96
96
97
97
Максимальна кількість вкладених викликів (включаючи перший) називається *глибина рекурсії*. У нашому випадку вона буде точно дорівнювати `n`.
98
98
99
-
Максимальна глибина рекурсії обмежена рушієм JavaScript. Кількість вкладених викликів, на яку точно можна розраховувати -10000. Деякі рушії дозволять працювати з ще більшою глибиною. Але навіть більшість з них можуть осилити не більше 100000 викликів. Є багато автоматичних оптимізацій, які допомагають уникнути переповнення стеку викликів ("оптимізація хвостових викликів", англ. tailcalls optimizations), але вони підтримуються далеко не всюди і працюють тільки в простих випадках.
99
+
Максимальна глибина рекурсії обмежена рушієм JavaScript. Кількість вкладених викликів, на яку точно можна розраховувати --10000. Деякі рушії дозволять працювати з ще більшою глибиною. Але навіть більшість з них можуть осилити не більше 100000 викликів. Є багато автоматичних оптимізацій, які допомагають уникнути переповнення стеку викликів ("оптимізація хвостових викликів", англ. "tail call optimizations"), але вони підтримуються далеко не всюди і працюють тільки в простих випадках.
100
100
101
101
Це обмежує застосування рекурсії, але вона все ще залишається дуже широко поширеною. Є багато завдань, де рекурсивний спосіб мислення дає простіший код, який легше підтримувати.
102
102
@@ -185,7 +185,7 @@ alert( pow(2, 3) );
185
185
186
186
Новий поточний контекст виконання знаходиться на малюнку вище (підпис виділений жирним шрифтом), а попередні контексти, які все ще бережуть в пам'яті, зображені на тому ж малюнку нижче.
187
187
188
-
Коли виконання підвиклику закінчиться, можна буде легко повернутись назад. Бо контекст зберігає як значення змінних, так і точне місце в коді, де він зупинився.
188
+
Коли виконання підвиклику закінчиться, можна буде легко повернутись назад. Бо контекст зберігає як значення змінних, так і точне місце в коді, де він зупинився.
189
189
190
190
```smart
191
191
Тут, на малюнку, ми використовуємо "на рядку", так як у нашому прикладі є лише один підвиклик в рядку, але, як правило, один рядок коду може містити декілька підвикликів, як `pow(...) +pow(...) +somethingElse(...)`.
@@ -328,7 +328,7 @@ let company = {
328
328
- Або відділ може бути розділеним на підрозділи, наприклад, `development` має дві гілки:`sites` та `internals`. Кожна з них має свій персонал.
329
329
- Можливо також, що коли відділ зростає, він розділяється на субвідділи (або команди).
330
330
331
-
Наприклад, відділ `sites` у майбутньому може бути розділений на команди для `siteA` і `siteB`. І І вони, потенційно, можуть бути розділені в подальшому. Це не зображено на малюнку, просто слід мати це на увазі.
331
+
Наприклад, відділ `sites` у майбутньому може бути розділений на команди для `siteA` і `siteB`. І вони, потенційно, можуть бути розділені в подальшому. Це не зображено на малюнку, просто слід мати це на увазі.
332
332
333
333
Тепер припустімо, що ми хочемо, щоб функція отримала суму всіх зарплат. Як ми можемо це зробити?
Ми можемо легко побачити принцип: для об’єкта `{...}` зроблені підвиклики, а масиви``[...]` -- "листя" рекурсійного дерева, вони дають негайний результат.
385
385
386
-
Зауважте, що код використовує пруткі можливості, які ми вже розглядали раніше:
386
+
Зауважте, що код використовує корисні функції, які ми вже розглядали раніше:
387
387
388
388
- Метод `arr.reduce` пояснено в розділі <info:array-methods>, щоб отримати суму масиву.
389
389
- Цикл `for(val ofObject.values(obj))` для ітерування значень об’єкта: `Object.values` повертає їх масив.
@@ -424,7 +424,7 @@ let arr = [obj1, obj2, obj3];
424
424
425
425
Єдині структурні модифікації, які не потребують масової перенумерації об’єктів, є ті, які працюють з кінцем масиву: `arr.push/pop`. Таким чином, масив може бути досить повільним для великих черг, коли ми повинні працювати з його початком.
426
426
427
-
Крім того, якщо нам дійсно потрібні швидкі вставка/видалення, ми можемо вибрати іншу структуру даних, яка називається [зв’язаний список](https://uk.wikipedia.org/wiki/Зв'язаний_список), англ. linked list.
427
+
Крім того, якщо нам дійсно потрібні швидкі вставка/видалення, ми можемо вибрати іншу структуру даних, яка називається [зв’язаний список](https://uk.wikipedia.org/wiki/Зв'язаний_список), англ. "linked list".
428
428
429
429
*Елемент зв’язаного списку* рекурсивно визначається як об’єкт з:
430
430
- `value`.
@@ -523,7 +523,7 @@ list.next = list.next.next;
523
523
## Підсумки
524
524
525
525
Терміни:
526
-
- *Рекурсія* - це термін програмування, який означає, що функція викликає саму себе. Рекурсивні функції можуть бути використані для вирішення завдань у елегантний спосіб.
526
+
- *Рекурсія* -- це термін програмування, який означає, що функція викликає саму себе. Рекурсивні функції можуть бути використані для вирішення завдань у елегантний спосіб.
527
527
528
528
Коли функція викликає себе, це називається *рекурсійний крок*. *База* рекурсії є функціональними аргументами, які роблять завдання таким простим, що функція не робить додаткових викликів.
0 commit comments