Calling a javascript function recursively Calling a javascript function recursively javascript javascript

Calling a javascript function recursively


Using Named Function Expressions:

You can give a function expression a name that is actually private and is only visible from inside of the function ifself:

var factorial = function myself (n) {    if (n <= 1) {        return 1;    }    return n * myself(n-1);}typeof myself === 'undefined'

Here myself is visible only inside of the function itself.

You can use this private name to call the function recursively.

See 13. Function Definition of the ECMAScript 5 spec:

The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.

Please note that Internet Explorer up to version 8 doesn't behave correctly as the name is actually visible in the enclosing variable environment, and it references a duplicate of the actual function (see patrick dw's comment below).

Using arguments.callee:

Alternatively you could use arguments.callee to refer to the current function:

var factorial = function (n) {    if (n <= 1) {        return 1;    }    return n * arguments.callee(n-1);}

The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode, however:

(From MDN): In normal code arguments.callee refers to the enclosing function. This use case is weak: simply name the enclosing function! Moreover, arguments.callee substantially hinders optimizations like inlining functions, because it must be made possible to provide a reference to the un-inlined function if arguments.callee is accessed. arguments.callee for strict mode functions is a non-deletable property which throws when set or retrieved.


You can access the function itself using arguments.callee [MDN]:

if (counter>0) {    arguments.callee(counter-1);}

This will break in strict mode, however.


You can use the Y-combinator: (Wikipedia)

// ES5 syntaxvar Y = function Y(a) {  return (function (a) {    return a(a);  })(function (b) {    return a(function (a) {      return b(b)(a);    });  });};// ES6 syntaxconst Y = a=>(a=>a(a))(b=>a(a=>b(b)(a)));// If the function accepts more than one parameter:const Y = a=>(a=>a(a))(b=>a((...a)=>b(b)(...a)));

And you can use it as this:

// ES5var fn = Y(function(fn) {  return function(counter) {    console.log(counter);    if (counter > 0) {      fn(counter - 1);    }  }});// ES6const fn = Y(fn => counter => {  console.log(counter);  if (counter > 0) {    fn(counter - 1);  }});