SlightlyLoony
Tera Contributor

The two developers at right (you know they don't work here, dressed like that!) were having quite the argument the other day. Brian asserted, spittle flying, that it's impossible in JavaScript to have an anonymous recursive function. Emily insulted several of his ancestors, called Brian some names we won't repeat here, and declared that of course it was possible — and even easy!

Friends called me in as a peacemaker, afraid that physical blows were in the immediate future. Emily and Brian agreed not to hurt me while I investigated.

So who was right — Brian or Emily?

Emily wins this one, to her great satisfaction.

Here's an example of a classic recursive function — computing the greatest common denominator of two numbers:


function gcd(x, y) {
return (y ==0) ? x : gcd(y, x % y);
}

gs.log(gcd(47437,77519));

When you run it, you get the answer 1157, which is correct. That is not an anonymous function, though. Anonymous functions have no name, and this one has a perfectly good name (gcd()). The absence of a name is why Brian thought it was impossible to have an anonymous recursive functions, because recursive functions (by definition) call themselves, just as this one does. And how could any function call itself without knowing its own name?

So how can Emily be right? Here's the solution she proposed:

var x = function(x, y) {
return gcd(x,y);

function gcd(x, y) {
return (y ==0) ? x : arguments.callee(y, x % y);
}
}

gs.log(x(47437,77519));

She gets points for coming up with a solution that actually works (if you run this, you'll get the right answer), and is, technically, an anonymous function. But Brian objected, pointing out that really all Emily was doing with this solution is wrapping a non-anonymous function (gcd()) in an anonymous wrapper. She's cheating, said he, and we could see him winding up again.

So I showed him the studly way to build an anonymous recursive function, using the quite satifyingly obscure callee property of the arguments object. "Huh?" said he, succintcly, staring at the code:

var x = function(x, y) {
return (y ==0) ? x : arguments.callee(y, x % y);
}

gs.log(x(47437,77519));

Brian couldn't argue with the fact that this code produced the correct answer, nor could he argue that it wasn't using a purely anonymous function. But how does it work?

The callee property contains a reference to the function whose arguments object it is contained by. In our example, that means it has exactly the same value as the variable x. But...the variable x cannot be known to the code inside the anonymous function, so that code can't invoke it. But the arguments object is known inside the function by definition — so the code inside the function is perfectly free to invoke the callee property as a function. Presto! the elusive anonymous recursive function.

So far as I can tell, the callee property serves only one useful purpose: to enable anonymous recursive functions. Nice of the JavaScript designers to include it, wasn't it?

I'm happy to report that Brian and Emily are now talking normally to each other again...