javascript: recursive anonymous function? javascript: recursive anonymous function? javascript javascript

javascript: recursive anonymous function?


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.


People talked about the Y combinator in comments, but no one wrote it as an answer.

The Y combinator can be defined in javascript as follows: (thanks to steamer25 for the link)

var Y = function (gen) {  return (function(f) {    return f(f);  }(function(f) {    return gen(function() {      return f(f).apply(null, arguments);    });  }));}

And when you want to pass your anonymous function:

(Y(function(recur) {  return function(data) {    data = data+1;    var nothing = function() {      recur(data);    }    nothing();  }})());

The most important thing to note about this solution is that you shouldn't use it.


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 argumentU (f => (console.log ('stack overflow imminent!'), U (f)))