HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Рекурсия в программировании - это вызов функции из этой же самой функции. В математике многие функции определены именно таким образом, поэтому и большинство языков программирования берет на вооружение этот подход. JavaScript здесь не является исключением: в определении функции вы можете использовать не только данные, определенные ранее, но и вызывать в теле функции саму определяемую функцию. Выглядит это так:</p>
1 <p>Рекурсия в программировании - это вызов функции из этой же самой функции. В математике многие функции определены именно таким образом, поэтому и большинство языков программирования берет на вооружение этот подход. JavaScript здесь не является исключением: в определении функции вы можете использовать не только данные, определенные ранее, но и вызывать в теле функции саму определяемую функцию. Выглядит это так:</p>
2 <p>Этот вызов будет выполняться бесконечно и кажется, что в этом нет никакого смысла. Попробуем осмыслить рекурсию на более повседневном примере. Допустим, у вас есть три книги на полке и вы хотите узнать, сколько есть возможных вариантов их перестановки.</p>
2 <p>Этот вызов будет выполняться бесконечно и кажется, что в этом нет никакого смысла. Попробуем осмыслить рекурсию на более повседневном примере. Допустим, у вас есть три книги на полке и вы хотите узнать, сколько есть возможных вариантов их перестановки.</p>
3 <p>Получается шесть уникальных комбинаций из трех книг. Из четырех - 24 комбинации. Из 13 - почти столько же, сколько людей на планете. 25 книг? Вариантов их перестановки больше, чем атомов в организме человека.</p>
3 <p>Получается шесть уникальных комбинаций из трех книг. Из четырех - 24 комбинации. Из 13 - почти столько же, сколько людей на планете. 25 книг? Вариантов их перестановки больше, чем атомов в организме человека.</p>
4 <p>Вообще, существует<em>n!</em>вариантов перестановки<em>n</em>книг. Факториал означает - перемножить все целые числа<em>от 1 до n</em>. Так что, 3! это<em>1 * 2 * 3</em>. Давайте напишем функцию факториала.</p>
4 <p>Вообще, существует<em>n!</em>вариантов перестановки<em>n</em>книг. Факториал означает - перемножить все целые числа<em>от 1 до n</em>. Так что, 3! это<em>1 * 2 * 3</em>. Давайте напишем функцию факториала.</p>
5 <p>Здесь что-то не так. Мы не знаем значение n изначально, в этом вся проблема. Из математики нам известны два условия для рекурсивного определения факториала: если n равно 0, тогда факториал - 1, это просто. Но если n не равно 0, тогда факториал - n*(n-1)!</p>
5 <p>Здесь что-то не так. Мы не знаем значение n изначально, в этом вся проблема. Из математики нам известны два условия для рекурсивного определения факториала: если n равно 0, тогда факториал - 1, это просто. Но если n не равно 0, тогда факториал - n*(n-1)!</p>
6 <p>Давайте попробуем вот так:</p>
6 <p>Давайте попробуем вот так:</p>
7 <p>Это может показаться странным. Мы вызываем функцию из функции, но… это та же самая функция! Все дело в том, что сама по себе функция - это не ящик, это его<em>описание</em>. Ящик создается лишь при вызове функции, а после того, как она выполнилась, ящик самоуничтожается. Поэтому когда вы вызываете ту же самую функцию из нее самой, просто создается еще один ящик.</p>
7 <p>Это может показаться странным. Мы вызываем функцию из функции, но… это та же самая функция! Все дело в том, что сама по себе функция - это не ящик, это его<em>описание</em>. Ящик создается лишь при вызове функции, а после того, как она выполнилась, ящик самоуничтожается. Поэтому когда вы вызываете ту же самую функцию из нее самой, просто создается еще один ящик.</p>
8 <p>Давайте это отследим: мы вызываем factorial(3). 3 это не 0, поэтому первое условие игнорируется. Функция хочет произвести умножение чисел и вернуть ответ, но она не может - ей нужно знать второе число, для чего она вызывает factorial(3 - 1) или factorial(2).</p>
8 <p>Давайте это отследим: мы вызываем factorial(3). 3 это не 0, поэтому первое условие игнорируется. Функция хочет произвести умножение чисел и вернуть ответ, но она не может - ей нужно знать второе число, для чего она вызывает factorial(3 - 1) или factorial(2).</p>
9 <p>Формируется новый идентичный ящик factorial, он принимает число 2, это не 0, так что он пробует произвести умножение и вернуть ответ, но не может - ему нужно знать второе число, поэтому он вызывает factorial(1).</p>
9 <p>Формируется новый идентичный ящик factorial, он принимает число 2, это не 0, так что он пробует произвести умножение и вернуть ответ, но не может - ему нужно знать второе число, поэтому он вызывает factorial(1).</p>
10 <p>Формируется новый идентичный ящик factorial, он принимает число 1 и это снова не 0. Еще одна попытка произвести умножение и вернуть результат, происходит вызов factorial(0) и этот ящик уже может мгновенно вернуть ответ - он возвращает 1.</p>
10 <p>Формируется новый идентичный ящик factorial, он принимает число 1 и это снова не 0. Еще одна попытка произвести умножение и вернуть результат, происходит вызов factorial(0) и этот ящик уже может мгновенно вернуть ответ - он возвращает 1.</p>
11 <p>1 возвращается в предыдущий ящик, умножается на 1 и ответ "1" возвращается в предыдущий ящик, умножается на 2 и ответ "2" возвращается в предыдущий ящик, умножается на 3 и ответ "6" возвращается во внешний мир и сохраняется в константе answer. Voilà!</p>
11 <p>1 возвращается в предыдущий ящик, умножается на 1 и ответ "1" возвращается в предыдущий ящик, умножается на 2 и ответ "2" возвращается в предыдущий ящик, умножается на 3 и ответ "6" возвращается во внешний мир и сохраняется в константе answer. Voilà!</p>
12 <p>Все это и есть рекурсия: что-то описывается через самого себя, содержит себя в своем описании. Когда дело касается математики или программирования, требуется два условия:</p>
12 <p>Все это и есть рекурсия: что-то описывается через самого себя, содержит себя в своем описании. Когда дело касается математики или программирования, требуется два условия:</p>
13 <ol><li>Простой<em>базовый</em>случай или<em>терминальный</em>сценарий. Это точка, в которой нужно остановиться. В нашем примере это 0: мы остановили вычисление факториала, когда в функцию был передан 0</li>
13 <ol><li>Простой<em>базовый</em>случай или<em>терминальный</em>сценарий. Это точка, в которой нужно остановиться. В нашем примере это 0: мы остановили вычисление факториала, когда в функцию был передан 0</li>
14 <li>Правило передвижения по рекурсии, углубление. В нашем случае это было n * factorial(n - 1)</li>
14 <li>Правило передвижения по рекурсии, углубление. В нашем случае это было n * factorial(n - 1)</li>
15 </ol><p>Еще один момент. Если проверить наш код с помощью линтера, то он выдаст ошибку no-else-return. Последуем рекомендациями линтера и отрефакторим код:</p>
15 </ol><p>Еще один момент. Если проверить наш код с помощью линтера, то он выдаст ошибку no-else-return. Последуем рекомендациями линтера и отрефакторим код:</p>
16 <p>Давайте проследим шаги еще раз, но с другой точки зрения, не заглядывая в ящики. Вот, как это выглядит пошагово:</p>
16 <p>Давайте проследим шаги еще раз, но с другой точки зрения, не заглядывая в ящики. Вот, как это выглядит пошагово:</p>
17 <p>Умножение не происходит пока мы спускаемся до базового случая функции factorial(0). А затем мы возвращаемся наверх, производя одно умножение за один шаг.</p>
17 <p>Умножение не происходит пока мы спускаемся до базового случая функции factorial(0). А затем мы возвращаемся наверх, производя одно умножение за один шаг.</p>
18 <p>Рекурсия широко используется, особенно в функциональном программировании, как уже упоминалось ранее. И не только для математических вычислений, а для множества других процессов!</p>
18 <p>Рекурсия широко используется, особенно в функциональном программировании, как уже упоминалось ранее. И не только для математических вычислений, а для множества других процессов!</p>
19 <p>Иногда информация в компьютере по своей природе требует рекурсивных функций. Например, веб-страницы состоят из HTML-элементов, и одни элементы могут входить в другие. Теги в тегах в тегах. И для эффективной обработки страницы браузеру требуется рекурсивно двигаться от уровня к уровню чтобы понять, в каком именно виде нужно вывести эти элементы на экран для пользователя.</p>
19 <p>Иногда информация в компьютере по своей природе требует рекурсивных функций. Например, веб-страницы состоят из HTML-элементов, и одни элементы могут входить в другие. Теги в тегах в тегах. И для эффективной обработки страницы браузеру требуется рекурсивно двигаться от уровня к уровню чтобы понять, в каком именно виде нужно вывести эти элементы на экран для пользователя.</p>
20 <p>Вы будете постоянно сталкиваться с рекурсией в этом и последующих курсах, потому что это невероятно мощная штука.</p>
20 <p>Вы будете постоянно сталкиваться с рекурсией в этом и последующих курсах, потому что это невероятно мощная штука.</p>