I can create a recursive function in a variable like so:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}
With this, functionHolder(3);
would output 3
2
1
0
. Let's say I did the following:
var copyFunction = functionHolder;
copyFunction(3);
would output 3
2
1
0
as above. If I then changed functionHolder
as follows:
functionHolder = function(whatever) {
output("Stop counting!");
Then functionHolder(3);
would give Stop counting!
, as expected.
copyFunction(3);
now gives 3
Stop counting!
as it refers to functionHolder
, not the function (which it itself points to). This could be desirable in some circumstances, but is there a way to write the function so that it calls itself rather than the variable that holds it?
That is, is it possible to change only the line functionHolder(counter-1);
so that going through all these steps still gives 3
2
1
0
when we call copyFunction(3);
? I tried this(counter-1);
but that gives me the error this is not a function
.
I know this is an old question, but I thought I'd present one more solution that could be used if you'd like to avoid using named function expressions. (Not saying you should or should not avoid them, just presenting another solution)
You can use the Y-combinator: (Wikipedia)
And you can use it as this:
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:
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: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:The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode, however:
Here's one very simple example:
Notice that the
counter
counts "backwards" in regards to whatslug
's value is. This is because of the position at which we are logging these values, as the function recurs before logging -- so, we essentially keep nesting deeper and deeper into the call-stack before logging takes place.Once the recursion meets the final call-stack item, it trampolines "out" of the function calls, whereas, the first increment of
counter
occurs inside of the last nested call.I know this is not a "fix" on the Questioner's code, but given the title I thought I'd generically exemplify Recursion for a better understanding of recursion, outright.
You can access the function itself using
arguments.callee
[MDN]:This will break in strict mode, however.