recursion - garevna/js-course GitHub Wiki

🎓 Рекурсия

Рекурсия - это процесс, в котором функция вызывает сама себя, прямо или косвенно

⚠️ Каждая рекурсивная функция должна иметь условие прерывания рекурсии

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

Хвостовая рекурсия - это когда последним исполняемым оператором рекурсивной функции будет оператор return с вызовом этой же функции

Простейший ( классический ) пример рекурсии - вычисление факториала

☕ 1️⃣

function factorial ( num, result ) {
   result = ( !result ? 1 : res ) * num--
   return num < 2 ? result : factorial ( num, result )
}

☕ 2️⃣

function factorial ( n, result = 1 ) {
   result *= n--
   return n < 2 ? result : factorial ( n, result )
}

☕ 3️⃣

function factorial ( n, result ) {
   while ( n > 1 )
      return factorial ( n-1, n * ( !result ? 1 : result ) )
   return result
}

☕ 4️⃣

function factorial ( n, result ) {
   return n < 2 ? !result ? 1 : result :
       factorial ( n-1, n * ( !result ? 1 : result ) )
}

☕ 5️⃣

Для того, чтобы избавиться от опционального параметра, используем замыкание:

function factor ( num ) {
   var res = 1
    return ( function fact () {
       res *= num
       return num < 2 ? res : fact ( --num )
    })()
}

В JavaScript каждый вызов функции добавит кадр вызова в стек

Когда вызов завершается, кадр удаляется из стека

Однако рекурсивная функция не завершается сразу

Она вернет рекурсивный вызов самой себя

Это будет каждый раз добавлять в стек контекст функции

Если хвостовая рекурсия достаточно глубокая, это может привести к переполнению стека и генерации исключения RangeError

Исключение RangeError возникает тогда, когда глубина рекурсии превышает 10000

💼 Упражнение

Разберите код функции circle

var circle = function ( radius ) {
        var elem = document.createElement ( "div" )
        document.body.appendChild ( elem )
        elem.style = `
             position: absolute;
             width: ${radius}px;
             height: ${radius}px;
             border-radius: 50%;
             border: solid 1px green;
        `
        if ( radius < 300 ) circle ( radius += 20 )
}

Вызовите функцию circle

⚠️ **GitHub.com Fallback** ⚠️