You can give the function a name, even when you're creating the function as a value and not a "function declaration" statement. In other words:

(function foo() { foo(); })();

is a stack-blowing recursive function. Now, that said, you probably don't may not want to do this in general because there are some weird problems with various implementations of Javascript. (note — that's a fairly old comment; some/many/all of the problems described in Kangax's blog post may be fixed in more modern browsers.)

When you give a name like that, the name is not visible outside the function (well, it's not supposed to be; that's one of the weirdnesses). It's like "letrec" in Lisp.

As for arguments.callee, that's disallowed in "strict" mode and generally is considered a bad thing, because it makes some optimizations hard. It's also much slower than one might expect.

edit — If you want to have the effect of an "anonymous" function that can call itself, you can do something like this (assuming you're passing the function as a callback or something like that):

asyncThingWithCallback(params, (function() {
  function recursive() {
    if (timeToStop())
      return whatever();
    recursive(moreWork);
  }
  return recursive;
})());

What that does is define a function with a nice, safe, not-broken-in-IE function declaration statement, creating a local function whose name will not pollute the global namespace. The wrapper (truly anonymous) function just returns that local function.

Answer from Pointy on Stack Overflow
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Glossary › Recursion
Recursion - Glossary | MDN
A recursive function can receive two inputs: a base case (ends recursion) or a recursive case (resumes recursion). The following Python code defines a function that takes a number, prints it, and then calls itself again with the number's value -1. It keeps going until the number is equal to 0, in which case it stops. ... The following code defines a function that returns the maximum size of the call stack available in the JavaScript runtime in which the code is run.
🌐
GeeksforGeeks
geeksforgeeks.org › javascript › how-to-understand-recursion-in-javascript
Recursion in JavaScript - GeeksforGeeks
The core elements of recursion define how a function repeatedly calls itself while progressing toward a stopping condition.
Published   January 16, 2026
People also ask

What is recursion in JavaScript?
Recursion is when a function calls itself to solve a problem. Each recursive call works on a smaller piece of the problem until it reaches a base case that stops the recursion. It's useful for tasks like tree traversal, calculating factorials, and processing nested data structures.
🌐
playcode.io
playcode.io › javascript › recursion
JavaScript Recursion: Complete Guide with Examples | Playcode
When should I use recursion instead of loops?
Use recursion when dealing with tree-like structures, nested data, or problems that naturally divide into smaller subproblems (like quicksort or mergesort). Use loops for simple iterations. Recursion can be more elegant for complex problems but may use more memory due to the call stack.
🌐
playcode.io
playcode.io › javascript › recursion
JavaScript Recursion: Complete Guide with Examples | Playcode
What is tail recursion?
Tail recursion is when the recursive call is the last operation in the function. Some languages optimize tail-recursive functions to reuse stack frames, preventing stack overflow. While JavaScript ES6 specifies tail call optimization, most browsers do not implement it.
🌐
playcode.io
playcode.io › javascript › recursion
JavaScript Recursion: Complete Guide with Examples | Playcode
🌐
JavaScript Tutorial
javascripttutorial.net › home › javascript tutorial › javascript recursive function
JavaScript Recursive Function
November 15, 2024 - This tutorial shows you how to use the recursion technique to develop a JavaScript recursive function, which is a function that calls itself.
🌐
freeCodeCamp
freecodecamp.org › news › recursion-in-javascript
What is Recursion in JavaScript?
April 2, 2025 - Recursion is a problem-solving technique in programming. In this article, you will learn how to use recursive functions in JavaScript. What is a Recursive Function? A recursive function is a function that calls itself somewhere within the body of the...
🌐
Programiz
programiz.com › javascript › recursion
JavaScript Recursion (with Examples)
The counter() function first displays count then checks if the value of count is greater than 1 with count > 1. If count > 1 evaluates to true, the program decreases the value of count and calls counter() with the new value of count (recursion).
🌐
Medium
medium.com › hackernoon › you-might-not-need-that-recursive-function-in-javascript-275651522185
You Might Not Need that Recursive Function in JavaScript | by Nick Scialli | HackerNoon.com | Medium
February 29, 2020 - When we encounter a problem like this, we tend to reach for recursion — often accomplished by creating a function that calls itself as many times as necessary. Recursion is extremely important in programming and many problems can only be solved by using it. That being said, recursion can be slower, fill up the call stack, and can be conceptually trickier. In this post, I will explore an example of a problem that seems to lend itself to a recursive solution, but can in fact be solved more efficiently through an understanding of JavaScript object references.
Find elsewhere
🌐
CodeSignal
codesignal.com › learn › courses › sorting-and-searching-algorithms-in-js › lessons › exploring-the-magic-of-recursion-in-javascript
Exploring the Magic of Recursion in JavaScript
In this function, similarly, with the factorial calculation, we pass Math.floor(num / 10) to the next recursion level, effectively dropping the last digit in each recursive call. ... Let's wrap up here. We dove into the sea of recursion, familiarized ourselves with vital concepts like base and recursive cases, and implemented a simple JavaScript recursive function.
🌐
Playcode
playcode.io › javascript › recursion
JavaScript Recursion: Complete Guide with Examples | Playcode
Recursion is when a function calls itself to solve smaller instances of a problem · Every recursive function needs a base case to stop and a recursive case to continue
Top answer
1 of 16
163

You can give the function a name, even when you're creating the function as a value and not a "function declaration" statement. In other words:

(function foo() { foo(); })();

is a stack-blowing recursive function. Now, that said, you probably don't may not want to do this in general because there are some weird problems with various implementations of Javascript. (note — that's a fairly old comment; some/many/all of the problems described in Kangax's blog post may be fixed in more modern browsers.)

When you give a name like that, the name is not visible outside the function (well, it's not supposed to be; that's one of the weirdnesses). It's like "letrec" in Lisp.

As for arguments.callee, that's disallowed in "strict" mode and generally is considered a bad thing, because it makes some optimizations hard. It's also much slower than one might expect.

edit — If you want to have the effect of an "anonymous" function that can call itself, you can do something like this (assuming you're passing the function as a callback or something like that):

asyncThingWithCallback(params, (function() {
  function recursive() {
    if (timeToStop())
      return whatever();
    recursive(moreWork);
  }
  return recursive;
})());

What that does is define a function with a nice, safe, not-broken-in-IE function declaration statement, creating a local function whose name will not pollute the global namespace. The wrapper (truly anonymous) function just returns that local function.

2 of 16
42

U combinator

By passing a function to itself as an argument, a function can recur using its parameter instead of its name! So the function given to U should have at least one parameter that will bind to the function (itself).

In the example below, we have no exit condition, so we will just loop indefinitely until a stack overflow happens

const U = f => f (f) // call function f with itself as an argument

U (f => (console.log ('stack overflow imminent!'), U (f)))

We can stop the infinite recursion using a variety of techniques. Here, I'll write our anonymous function to return another anonymous function that's waiting for an input; in this case, some number. When a number is supplied, if it is greater than 0, we will continue recurring, otherwise return 0.

const log = x => (console.log (x), x)

const U = f => f (f)

// when our function is applied to itself, we get the inner function back
U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)
// returns: (x => x > 0 ? U (f) (log (x - 1)) : 0)
// where f is a reference to our outer function

// watch when we apply an argument to this function, eg 5
U (f => x => x > 0 ? U (f) (log (x - 1)) : 0) (5)
// 4 3 2 1 0

What's not immediately apparent here is that our function, when first applied to itself using the U combinator, it returns a function waiting for the first input. If we gave a name to this, can effectively construct recursive functions using lambdas (anonymous functions)

const log = x => (console.log (x), x)

const U = f => f (f)

const countDown = U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)

countDown (5)
// 4 3 2 1 0

countDown (3)
// 2 1 0

Only this isn't direct recursion – a function that calls itself using its own name. Our definition of countDown does not reference itself inside of its body and still recursion is possible

// direct recursion references itself by name
const loop = (params) => {
  if (condition)
    return someValue
  else
    // loop references itself to recur...
    return loop (adjustedParams)
}

// U combinator does not need a named reference
// no reference to `countDown` inside countDown's definition
const countDown = U (f => x => x > 0 ? U (f) (log (x - 1)) : 0)

How to remove self-reference from an existing function using U combinator

Here I'll show you how to take a recursive function that uses a reference to itself and change it to a function that employs the U combinator to in place of the self reference

const factorial = x =>
  x === 0 ? 1 : x * factorial (x - 1)
  
console.log (factorial (5)) // 120

Now using the U combinator to replace the inner reference to factorial

const U = f => f (f)

const factorial = U (f => x =>
  x === 0 ? 1 : x * U (f) (x - 1))

console.log (factorial (5)) // 120

The basic replacement pattern is this. Make a mental note, we will be using a similar strategy in the next section

// self reference recursion
const foo =         x => ...   foo (nextX) ...

// remove self reference with U combinator
const foo = U (f => x => ... U (f) (nextX) ...)

Y combinator

related: the U and Y combinators explained using a mirror analogy

In the previous section we saw how to transform self-reference recursion into a recursive function that does not rely upon a named function using the U combinator. There's a bit of an annoyance tho with having to remember to always pass the function to itself as the first argument. Well, the Y-combinator builds upon the U-combinator and removes that tedious bit. This is a good thing because removing/reducing complexity is the primary reason we make functions

First, let's derive our very own Y-combinator

// standard definition
const Y = f => f (Y (f))

// prevent immediate infinite recursion in applicative order language (JS)
const Y = f => f (x => Y (f) (x))

// remove reference to self using U combinator
const Y = U (h => f => f (x => U (h) (f) (x)))

Now we will see how it's usage compares to the U-combinator. Notice, to recur, instead of U (f) we can simply call f ()

const U = f => f (f)

const Y = U (h => f => f (x => U (h) (f) (x)))

Y (f => (console.log ('stack overflow imminent!'),  f ()))

Now I'll demonstrate the countDown program using Y – you'll see the programs are almost identical but the Y combinator keeps things a bit cleaner

const log = x => (console.log (x), x)

const U = f => f (f)

const Y = U (h => f => f (x => U (h) (f) (x)))

const countDown = Y (f => x => x > 0 ? f (log (x - 1)) : 0)

countDown (5)
// 4 3 2 1 0

countDown (3)
// 2 1 0

And now we'll see factorial as well

const U = f => f (f)

const Y = U (h => f => f (x => U (h) (f) (x)))

const factorial = Y (f => x =>
  x === 0 ? 1 :  x * f (x - 1))

console.log (factorial (5)) // 120

As you can see, f becomes the mechanism for recursion itself. To recur, we call it like an ordinary function. We can call it multiple times with different arguments and the result will still be correct. And since it's an ordinary function parameter, we can name it whatever we like, such as recur below -

const U = f => f (f)

const Y = U (h => f => f (x => U (h) (f) (x)))

const fibonacci = Y (recur => n =>
  n < 2 ? n : recur (n - 1) +  (n - 2))

console.log (fibonacci (10)) // 55


U and Y combinator with more than 1 parameter

In the examples above, we saw how we can loop and pass an argument to keep track of the "state" of our computation. But what if we need to keep track of additional state?

We could use compound data like an Array or something...

const U = f => f (f)

const Y = U (h => f => f (x => U (h) (f) (x)))

const fibonacci = Y (f => ([a, b, x]) =>
  x === 0 ? a : f ([b, a + b, x - 1]))

// starting with 0 and 1, generate the 7th number in the sequence
console.log (fibonacci ([0, 1, 7])) 
// 0 1 1 2 3 5 8 13

But this is bad because it's exposing internal state (counters a and b). It would be nice if we could just call fibonacci (7) to get the answer we want.

Using what we know about curried functions (sequences of unary (1-paramter) functions), we can achieve our goal easily without having to modify our definition of Y or rely upon compound data or advanced language features.

Look at the definition of fibonacci closely below. We're immediately applying 0 and 1 which are bound to a and b respectively. Now fibonacci is simply waiting for the last argument to be supplied which will be bound to x. When we recurse, we must call f (a) (b) (x) (not f (a,b,x)) because our function is in curried form.

const U = f => f (f)

const Y = U (h => f => f (x => U (h) (f) (x)))

const fibonacci = Y (f => a => b => x =>
  x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)

console.log (fibonacci (7)) 
// 0 1 1 2 3 5 8 13


This sort of pattern can be useful for defining all sorts of functions. Below we'll see two more functions defined using the Y combinator (range and reduce) and a derivative of reduce, map.

const U = f => f (f)

const Y = U (h => f => f (x => U (h) (f) (x)))

const range = Y (f => acc => min => max =>
  min > max ? acc : f ([...acc, min]) (min + 1) (max)) ([])

const reduce = Y (f => g => y => ([x,...xs]) =>
  x === undefined ? y : f (g) (g (y) (x)) (xs))
  
const map = f =>
  reduce (ys => x => [...ys, f (x)]) ([])
  
const add = x => y => x + y

const sq = x => x * x

console.log (range (-2) (2))
// [ -2, -1, 0, 1, 2 ]

console.log (reduce (add) (0) ([1,2,3,4]))
// 10

console.log (map (sq) ([1,2,3,4]))
// [ 1, 4, 9, 16 ]


IT'S ALL ANONYMOUS OMG

Because we're working with pure functions here, we can substitute any named function for its definition. Watch what happens when we take fibonacci and replace named functions with their expressions

/* const U = f => f (f)
 *
 * const Y = U (h => f => f (x => U (h) (f) (x)))
 *
 * const fibonacci = Y (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1)
 *
 */

/*
 * given fibonacci (7)
 *
 * replace fibonacci with its definition
 * Y (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
 *
 * replace Y with its definition
 * U (h => f => f (x => U (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
//
 * replace U with its definition
 * (f => f (f)) U (h => f => f (x => U (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
 */

let result =
  (f => f (f)) (h => f => f (x => h (h) (f) (x))) (f => a => b => x => x === 0 ? a : f (b) (a + b) (x - 1)) (0) (1) (7)
  
console.log (result) // 13

And there you have it – fibonacci (7) calculated recursively using nothing but anonymous functions

🌐
JavaScript in Plain English
javascript.plainenglish.io › the-most-important-thing-about-recursive-functions-in-javascript-5f71147ea9ba
One Thing People Forget About Recursive Functions in JavaScript | by Diederik Mathijs | JavaScript in Plain English
June 15, 2021 - When we call functions recursively, behind the screens, our call stack will grow. This is visible in the image above. What if we call the fibonacci function with integer value 100,000. How will it affect our application? In JavaScript, the engine will step in if it thinks that the call stack grows too much and should be stopped.
🌐
JavaScript.info
javascript.info › tutorial › the javascript language › advanced working with functions
Recursion and stack
Any recursion can be rewritten as a loop. The loop variant usually can be made more effective. …But sometimes the rewrite is non-trivial, especially when a function uses different recursive subcalls depending on conditions and merges their results or when the branching is more intricate.
🌐
Medium
medium.com › nerd-for-tech › an-introduction-to-recursion-in-javascript-8a42b200ec0a
An introduction to recursion in Javascript | by Brian Blankenship | Nerd For Tech | Medium
July 10, 2021 - Don’t tell the others I said that though, they may consider that a form of blasphemy. *cough*. At it’s heart, recursion is just a function calling its self from within (or an higher order function calling an lower-order function x amount ...
🌐
W3Schools
w3schools.com › go › go_function_recursion.php
Go Recursion Functions
In the following example, factorial_recursion() is a function that calls itself. We use the x variable as the data, which decrements (-1) every time we recurse. The recursion ends when the condition is not greater than 0 (i.e.
🌐
Medium
jasspencer.medium.com › recursion-in-javascript-b80889b4478d
Recursion in JavaScript. Getting asked what recursive functions… | by Jas Spencer | Medium
April 9, 2021 - If it doesn’t, the function will be called again but will now call it with the value of n minus 1. The function will continue to call itself until the base case is met. ... We set an initial value of n, like 5. As 5 is not equal to 0, we get the value of 5 times the new value of n, which is 4. As 4 is still not equal to 0… this is where the recursion comes in.
🌐
GeeksforGeeks
geeksforgeeks.org › dsa › introduction-to-recursion-2
Introduction to Recursion - GeeksforGeeks
Break the problem down into smaller versions of itself, and call the function recursively to solve each subproblem. Step3 - Ensure the recursion terminates: Make sure that the recursive function eventually reaches the base case, and does not enter an infinite loop.
Published   2 weeks ago
🌐
DEV Community
dev.to › kadeesterline › recursion-in-javascript-3jk4
Recursion in JavaScript - DEV Community
June 28, 2022 - We know that every time we call a function it's put on top of the call stack until it's evaluated and then popped off the top of the call stack. With recursion, you just keep calling the same function and keep pushing it onto the call stack.
🌐
Love Coding
love-coding.pl › strona główna › javascript › javascript – recursive function example
JavaScript - Recursive function example
February 1, 2026 - The sumArray function goes through all elements of the array. If an element is another array, the function calls itself (recursion). If the element is a number, it adds it to the total.
🌐
SitePoint
sitepoint.com › blog › javascript › recursion in functional javascript
Recursion in Functional JavaScript — SitePoint
November 11, 2024 - M. David Green demonstrates the powerful, but dizzying concept of recursion by refactoring normal for and while loops to use functions that call themselves.
🌐
freeCodeCamp
forum.freecodecamp.org › javascript
Javascript recursive functions - JavaScript - The freeCodeCamp Forum
October 11, 2020 - Good evening friends Please do anyone has a solid of understanding of recursive functions. I just can’t figure what is happening in the background with the recursive functions. for example function multiply(arr, n) { if (n