DEV Community

Cover image for Introduction to Recursion in JavaScript: How It Works and How to Use It
Alex Devero
Alex Devero

Posted on • Originally published at blog.alexdevero.com

Introduction to Recursion in JavaScript: How It Works and How to Use It

Recursion is one of those programming topics that can sound intimidating. This is especially true if you are new to programming. In this tutorial, you will learn all you need to know about it. You will learn what recursion is, how recursion in JavaScript works and also how to implement it.

A quick introduction

The simplest way to describe what recursion is by saying that it is a function that calls itself. This type of function is called "recursive function". It doesn't matter if it is recursion in JavaScript or any other language. The main idea is that you have a function and this function calls itself, at least once.

// Simple recursive function
function recursiveFunction() {
  // Call the recursive function again
  recursiveFunction()
}

// Call the recursiveFunction()
recursiveFunction()
Enter fullscreen mode Exit fullscreen mode

That said, recursive function is not just any function. There are some conditions every recursive function has to meet. This is not necessary just so you can call that function a recursion. It is also necessary to make that recursion work properly. Here is the potential problem.

Let's say you have a function. This function calls itself. What happens when you call this function? Well, it will call itself. What happens next? When that function calls itself it will call itself again, and again and again. The problem is that there is no point at which the function is terminated. The result is an infinite loop.

For example, this will happen if you try to run the function in the example above. When you run that function, you will get an error Uncaught RangeError: Maximum call stack size exceeded. You can avoid this problem, creating an infinite loop, by adding a base case to the recursive function.

Base case

A base case is a fancy name for a specific condition. It is also called "base condition". This condition will force the function to do one of two things. If the condition evaluates to false, the recursive function will call itself again. If the condition evaluates to true, the recursive function will return a value.

The easiest way to create this base case is by using simple if...else statement. Inside one block, either if or else depending on the condition, you will return some value. Inside the other block, you will call the recursive function again. This will allow you to terminate the function at the right time.

// Simple recursive function
function recursiveFunction() {
  // Add base case
  if (/* condition */) {
    // Call the recursive function again
    recursiveFunction()
  } else {
    // Return something instead of calling
    // the recursive function again
  }
}

// Call the recursive function
recursiveFunction()
Enter fullscreen mode Exit fullscreen mode

JavaScript will terminate function execution when it encounters a return statement. This mean that you don't really have to use if...else statement. You need just the if part. If something, return something. Otherwise, you can let JavaScript skip the if...else and continue.

// Recursive function with shorter condition
function recursiveFunction() {
  // Add base case
  if (/* condition */) {
    // If condition evaluates to true
    // terminate this function call
    // by returning something
    return /* some value */
  }

  // Otherwise, call the recursive function again
  recursiveFunction()
}

// Call the recursive function
recursiveFunction()
Enter fullscreen mode Exit fullscreen mode

This is actually not the shortest version. You can make the base condition, and the whole function, even shorter. You can replace the if...else statement with ternary operator. This way, you can reduce the whole recursive function almost a one-liner. If you use an arrow function than literally to a one-liner.

// Recursive function with ternary operator
function recursiveFunction() {
  // Add base case
  return (/* condition */) ? /* some value */ : recursiveFunction()
}

// Call the recursive function
recursiveFunction()
Enter fullscreen mode Exit fullscreen mode

How to choose the best base case

What is the best candidate for the base case? This depends on what you want to achieve with your recursive function. For exampled, let's say you want to use recursion to calculate factorial. This is the most popular example for recursion. In case of a factorial, think about what is the lowest number you can use.

For factorial, the lowest number is 1. Factorial of 1 (1!) will always result to one. This makes 1 the best candidate for base case because it the smallest number, or level, you can get to. If you want to count numbers from X down to 0, 0 will be the lowest number. It will also be the best candidate for base case.

If you want to do the opposite and count upwards, the base will be the highest number you want to reach. Another example could be reversing a simple string. In that situation, the base case would be that the length of the string must be more than 0. It doesn't make sense to continue reversing an empty string.

How it actually works: A quick introduction to call stack

You know what recursion is and what it looks like so you can recognize it when you see it. You also know what is a base case. Now, let's take a look at how it actually works. Especially, how it works in JavaScript, since this will be the programming language you are the most familiar with.

To understand how recursion works, you need to know at least a little about about call stack. Call stack is mechanism that is built in JavaScript. JavaScript uses it to keep track of all function calls. Let's say you call a function. When you do this, JavaScript will add that function to the call stack.

When that function call is finished, JavaScript will automatically remove that function call from the call stack and goes to another one below, if there is any. However, if the function you called calls another function, something different happens. When that second function is called, JavaScript will add it to the call stack as well.

If that second function also calls a function, JavaScript will also add it at the top of the call stack. This repeats as long as there are function calls in the current chain of function. There are three important things you need to know. The first thing is that JavaScript will put that second call above the first.

JavaScript will add that function call on top of it, on top of the whole call stack. The second thing is that JavaScript executes calls in the call stack from the top to the bottom. This means that the first function call that was added to the call stack will be executed as last.

Conversely, the last function call that was added to the call stack will be executed as first. This is called LIFO principle. The third thing is that when JavaScript encounters function call it will stop executing the current call, execute that new call, and anything inside the newly called function.

Only when that newly called function is executed JavaScript will return to the previous call and finish executing that one. This will repeat for each function in the call stack.

function funcFour() {
  // some code to execute
}

function funcThree() {
  funcFour()
  // Execution of funcThree() is paused on the line above
  // until funcFour() is finished
}

function funcTwo() {
  funcThree()
  // Execution of funcTwo() is paused on the line above
  // until funcThree() is finished
}

function funcOne() {
  funcTwo()
  // Execution of funcOne() is paused on the line above
  // until funcTwo() is finished
}

// Call the funcOne()
funcOne()

// Call stack at this moment:
// funcFour() - executed as first (top of the stack)
// funcThree() - waiting for funcFour() to finish
// funcTwo() - waiting for funcThree() to finish
// funcOne() - waiting for funcTwo() to finish

// README:
// funcFour() is at the top of the stack
// and its function call will be finished as first
// after that execution will return to funcThree()
// when funcThree() is finished execution will return to funcTwo()
// when funcTwo() is finished execution will return to funcOne()
// when funcOne() is finished the call stack will be empty
Enter fullscreen mode Exit fullscreen mode

Recursive factorial function, call stack and analysis

Now, let's use this information about call stack to understand how recursion in JavaScript works. To illustrate this better let's take a recursive function to calculate a factorial. This function will accept a single parameter, a number for which it will calculate a factorial.

The base case for this function will be that the number you passed as argument must be equal to 1. When this situation happens, the function will return that number. It will return 1. Otherwise, it will return the number multiplied by the result of calling itself with the number decreased by 1 passed as an argument.

// Recursive function to calculate factorial
function calculateFactorial(num) {
  // Base case
  if (num === 1) {
    // The value of "num" here will be 1
    return num
  }

  return num * calculateFactorial(num - 1)
}

// Shorter version with ternary operator
function calculateFactorial(num) {
  // Base case
  return (num === 1) ? num : num * calculateFactorial(num - 1)
}

// Test the calculateFactorial()
calculateFactorial(4)
// Output:
// 24

// Test the calculateFactorial() again
calculateFactorial(9)
// Output:
// 362880

// Test the calculateFactorial() one more time
calculateFactorial(1)
// Output:
// 1
Enter fullscreen mode Exit fullscreen mode

Let's analyze the execution of the calculateFactorial() function. To keep this short, let's use 4 as the number for which we want to calculate the factorial. When you call the function with number 4 as an argument JavaScript will add it to the call stack. Since 4 is not equal to 1 calculateFactorial() will be called again.

At this moment, calculateFactorial() will be called not with number 4, but number 3 passed as an argument. Subsequent calls are always with number decreased by 1. JavaScript will add that second call to the call stack as well. It will add it on the top of the previous call of calculateFactorial() with number 4.

The number is still not equal to 1. So another call of calculateFactorial() function will be executed. The number passed in as an argument will now be 2. JavaScript will add this call at the top of the call stack and call calculateFactorial() function again. The number will be now 1.

This number meets the base case so the calculateFactorial() function will now return the number and it will not call itself again. The chain of calls is now over and we are at the top of the call stack.

// Recursive function to calculate factorial
function calculateFactorial(num) {
  // Base case
  return (num === 1) ? return num : num * calculateFactorial(num - 1)
}

// Test the calculateFactorial()
calculateFactorial(4)

// Call stack after calling calculateFactorial(4):
// calculateFactorial(1) - top of the stack, first out
// calculateFactorial(2)
// calculateFactorial(3)
// calculateFactorial(4) - bottom of the stack, last out
Enter fullscreen mode Exit fullscreen mode

What happens next? When we are at the top of the stack and there are no more calls, JavaScript will start moving to the bottom of the stack. During this, JavaScript will also start returning values of all function calls in the stack. With each returned value one function call will be removed from the stack.

The most interesting part are the values returned from all those calls. Do you remember the num * calculateFactorial(num - 1) line in the code for the calculateFactorial() function? Those values returned by calls in the stack will basically replace the calculateFactorial(num - 1) part.

The line will now look something like num * "num" (returned by the previous call). For each call in the stack, the num will be multiplied by the result of the previous call. The calculateFactorial(1) is the last call at the top of the stack and its return value will be returned as first.

There is no previous call and the function says that this number should be returned. This is the (num === 1) ? return num : part. So, the first returned value is 1. The next call is in the call stack is calculateFactorial(2). This is not the last call so the (num === 1) ? return num : line doesn't apply here.

Instead, we have to apply the num * calculateFactorial(num - 1). The first num is the number passed as parameter to the current call: 2. The calculateFactorial(num - 1) is the number returned by the last call: 1. So, num * calculateFactorial(num - 1) will result in 2 * 1.

The next call in the call stack is calculateFactorial(3). Just like in the previous case, we have to apply the num * calculateFactorial(num - 1). The first num is again the number passed to the current call: 3. The calculateFactorial(num - 1) is the number returned by the last call: 2.

The result of last call was 2 * 1. That's why calculateFactorial(num - 1) now translates to 2. So, num * calculateFactorial(num - 1) will translate to 3 * 2. The calculateFactorial(4) call was the last call, at the bottom of the stack. The num passed to the current call is 4.

The result of calculateFactorial(num - 1) returned by the previous call, calculateFactorial(3), was 6 (result of 3 * 2). So, now, num * calculateFactorial(num - 1) translates to 4 * 6. This makes the value returned by the current and last call 24. This is also the final result of your factorial calculation.

// Recursive function to calculate factorial
function calculateFactorial(num) {
  // Base case
  return (num === 1) ? return num : num * calculateFactorial(num - 1)
}

// Test the calculateFactorial()
calculateFactorial(4)

// Call stack after calling calculateFactorial(4):
// calculateFactorial(1)
//  - returns 1

// calculateFactorial(2)
// - returns 2 * 1 (1 is value returned from calculateFactorial(1))

// calculateFactorial(3)
//  - returns 3 * 2 (2 is value returned from calculateFactorial(2))

// calculateFactorial(4)
//  - returns 4 * 6 (6 is value returned from calculateFactorial(4))
Enter fullscreen mode Exit fullscreen mode

Another two examples of recursion in JavaScript

Before we end this tutorial, let's take a look at few examples of recursion in JavaScript. You already know how to use recursion to calculate factorial of any given number. Let's take a quick look at another two examples of recursive functions.

Recursive function for countdown

One good example to demonstrate implementation of recursion in JavaScript can be a function that counts down to 0, and prints number for each recursive call. The base case for this recursive function will be if the number passed, when decreased by one, is bigger than 0.

Only if the number is bigger than 0 the function will be called again. Otherwise, there will be nothing more to do so the function will terminate itself.

// Recursive function for countdown
function countdown(num) {
  // Print the number passed
  // to the current recursive call
  console.log(num)

  // Base case
  if (num - 1 > 0) {
    // If current number decreased by 1
    // is higher than 0 call countdown() again
    // with number decreased by 1
    return countdown(num - 1)
  }
}

// Call the countdown() function
countdown(11)
// Output:
// 11
// 10
// 9
// 8
// 7
// 6
// 5
// 4
// 3
// 2
// 1
Enter fullscreen mode Exit fullscreen mode

Recursive function for reversing string

The second example of an implementation of recursion in JavaScript will be a function that reverses a string. This function will accept string as a parameter. The base case will be if the length of the string is bigger than 1. If this condition is true, the function will call itself.

The string for this subsequent call will be the string from the current call without the first character. In addition, this first character will be added to end of the value returned by the next call.

// Recursive function for reversing string
function reverseString(str) {
  // Base case
  if (str.length >= 1) {
    // If the length of the string is bigger than 1
    // call the reverseString() function again,
    // pass in pass in the string without the first character
    // and then add the character and the end
    return reverseString(str.substring(1)) + str.charAt(0)
  }

  // Otherwise, return the string
  return str
}

// Call the reverseString() function
reverseString('Hello')
// Output:
// 'olleH'
Enter fullscreen mode Exit fullscreen mode

Conclusion: Introduction to recursion in JavaScript

Recursion is an advanced topic that can be very hard to fully grasp. However, it is worth the time to learn to learn about it. Recursion can be a very useful tool to solve some problems better and faster. I hope that this tutorial helped you understand recursion in JavaScript works and what it is in general.

Top comments (0)