Это первая серия таймеров.

Сегодня я хотел бы объяснить «Рекурсия».

Честно говоря, довольно сложно понять рекурсию. Я повторяюсь много раз в этой статье, но это и есть рекурсия.

Пожалуйста, наберитесь терпения и читайте медленно.

Определение рекурсии — это «функция, которая возвращает сама себя». В моем предыдущем посте я объяснил о «замыкании», которое возвращает функцию с переменной. Хотя они выглядят одинаково, замыкание возвращает функцию, которая еще не была вызвана.



Однако в случае рекурсии он возвращает собственную функцию и вызывает ее.

В принципе, это выглядит как на гифке ниже. (Не смотри на это так много, тебя тошнит...)

Давайте посмотрим на пример ниже.

(Возможно, вы захотите сделать снимок экрана или просто записать приведенный ниже фрагмент и прочитать эту статью, просматривая ее.)

Есть функция добавить. Он вызывается с аргументом 3 в строке 9.

В функции есть оператор if, а после ключевого слова else в строке 5 функция add возвращает x + add(x - 1).

Это что? Мы знаем, что x равно 3, потому что вызывается add(3).

Но что такое добавить(x-1)?

Это означает, что функция add вызывается с аргументом x -1 в операторе return.

В примере x равно 3, поэтому добавить(x - 1) равнозначно добавить(2). >.

x + add(x-1) === 3 + add(2); 
//I invoked the function add(3) so "x" = 3;

В JavaScript имя функции в скобках означает вызов функции.

Итак, в строке 5 функция add вызывается с аргументом 2 в операторе return функции add.

Что сейчас произойдет?

Функция add вызвала саму функцию add с аргументом 2, поэтому мы возвращаемся к строке 1 и запускаем функцию add снова! (2-я реализация)

Во второй реализации переменная x равна 2.

Условие (x === 0) по-прежнему ложно, поэтому строки 2 и 3 игнорируются, и мы переходим к строке 5.

О, опять?

Да, мы возвращаемся к строке 5, и вторая реализация add возвращает функцию add с аргументом (x - 1) и вызывается.

//2nd implementation "add"
x + add(x-1) === 2 + add(1); 
//I invoked the function add(2) so "x" = 2;

Затем мы возвращаемся к строке 1 и снова запускаем функцию «добавить»! (3-я реализация)

В третьей реализации переменная x равна 1.

В условии (x === 0) по-прежнему ложно, поэтому строки 2 и 3 игнорируются, и мы переходим к строке 5.

О, опять?

Мы снова в строке 5, и третья реализация add возвращает функцию add с аргументом (x - 1) и вызывается.

//3rd implementation "add"
x + add(x-1) === 1 + add(0); 
//I invoked the function add(1) so "x" = 1;

Затем мы возвращаемся к строке 1 и снова запускаем функцию add! (4-я реализация)

В четвертой реализации переменная x равна 0.

Наконец, условие (x === 0) верно, и мы переходим к строкам 2 и 3.

В строке 3 функция add возвращает 1.

Здорово! Получаем ответ!

//4th implementation "add"
if(x === 0){
  return 1; 
//x is "0" and it matches with condition! So, return "1".

Отлично, но… мы все еще на полпути к полной рекурсии.

Функция add возвращает результат 1. Но для чего этот результат?

Помните, мы реализовали функцию добавить 4 раза.

И компьютер запоминает каждый шаг.

Это называется стек вызовов. Компьютер складывает каждый шаг при вызове функции и удаляет каждый стек, когда его действие возврата завершено.

В четвертой реализации функция add возвращает 1 и завершается, поэтому четвертая реализация add — это удалены из стека вызовов, но у нас все еще есть 3-я, 2-я и 1-я реализации add в стеке вызовов, поскольку эти возвраты еще не завершены.

//4th implementation "add"
const add(0) => {// x - 1 is "0"  it is invoked from add(1 - 1);
  if(x === 0){
    return 1; // x === 0 is true, return 1. Complete!
  } else {
    return x + add(x - 1);
  };
};

Каково возвращаемое значение третьей реализации add?

Это x + add(x - 1).

//3rd implementation "add"
x + add(x-1) === 1 + add(0); 

Но мы знаем, что add(0) уже вернул значение 1.

Итак, есть небольшое изменение.

//3rd implementation "add"
x - add(x-1) === 1 + 1; // return "2"

О, мы получили ответ! add(1) возвращает 2.

Затем третья реализация add удаляется из стека вызовов.

Хорошо… что дальше?

Да, мы должны перейти ко второй реализации добавить.

//2nd implementation "add"
x + add(x-1) === 2 + add(1); 

Мы знаем, что add(1) возвращает 2.

//2nd implementation "add"
x + add(x-1) === 2 + 2; // return "4"

Итак, возвращаемое значение add(2) равно 4.

Затем вторая реализация add удаляется из стека вызовов.

Мы почти у цели.

Вернитесь к первой реализации add.

//1st implementation "add"
x + add(x-1) === 3 + add(2); 

Мы знаем, что add(2) возвращает 4.

//1st implementation "add"
x + add(x-1) === 3 + 4; // return "7"

А ниже полный фрагмент 1-й реализации.

//1st implementation "add"
const add(3) => {
  if(x === 0){
    return 1;
  } else {
    return 3 + 4; which is "7", complete!
  };
};

Наконец, мы получили ответ 7, а первая реализация add удалена из стека вызовов, миссия выполнена!

Вот как работает рекурсия, и она заманивает вас в лабиринт.

Ключевой момент рекурсии — «функция вызывает себя до самого конца функции».

В приведенном ниже ролике показан весь процесс, который я объяснил.

(Возможно, вы захотите сохранить фрагмент и смотреть его, просматривая его.)

Последняя вещь.

Вы должны быть осторожны с установкой конечной точки при запуске рекурсии.

В примере оператор «if(x===0){ … » является конечной точкой.

В противном случае функция будет вызывать функцию снова и снова и никогда не остановится.

Функция вызывает сама себя, и вызываемая функция вызывает сама себя, и вызываемая функция вызывает сама себя…

Это называется бесконечным циклом, и он приведет к сбою вашего браузера. Вы должны убить его, как только это произойдет.

Надеюсь, вы узнали немного о рекурсии из моих статей.

Спасибо за чтение!