The one issue that’s weird about JavaScript that I’ve found is that it has no compiler: the first time you find a bug is when you run your code, not when you compile it. So, since I’m adamant about writing “good” JavaScript code as I write it, I’ve installed a couple of JSLint plug-ins, one for Visual Studio and one for Sublime Text. JSLint is Douglas Crockford’s linter for JavaScript and, although utterly (perhaps barmily?) strict in certain areas, is the one I’ve settled on for checking/validating my code before I run it.
It’s got to the point that I’ve got into the habit of declaring the following JSLint comment at the top of all my JS files: /*jslint white this browser */
. This ensures that JSLint won’t complain about my indentation policy (that’s the white
keyword), that it allows a “sloppy” use of this
, and that it predeclares that all the relevant browser global variables are valid (since JSLint will complain bitterly about globals, and rightly so – you should see some of the broken code out there).
Anyway, today I happened to be messing around with recursion as part of my investigations into writing functional JavaScript (that is, JavaScript code written in a functional programming manner, which I shall be discussing further in the near future). In functional programming, recursion is infinitely more preferred than iteration, say via a for
loop or similar. Anyway, here’s some example code illustrating how I was doing the recursion (this is not the actual code, but it will suffice):
var factorial = function (value) {
"use strict";
if (value === 1) {
return 1;
}
return value * factorial(value - 1);
};
As you can see, a pretty solid and simple example of tail-end recursion for calculating a factorial.
(Aside: from what I’ve been reading, JavaScript is soon to get tail-end recursion removal, which will make this style of functional programming much more palatable performance-wise. The reason for this is that the compiler/interpreter doesn’t have to construct a new stack frame in order to make the recursive call, and then destroy it when it returns; all it has to do it modify the current one and loop. A lot faster. But, as I said, not yet available in current JavaScript interpreters.)
The problem I was running into was JSLint was complaining that factorial
was out of scope on the recursive call statement.
#1 'factorial' is out of scope.
return value * factorial(value - 1); // Line 8, Pos 18
Hmm, looks OK to me: there’s the declaration of the variable called factorial
and it’s set equal to the function expression. If I run this code it works just fine.
It turns out though that JSLint is of the opinion that the function expression containing the recursive call hasn’t yet been fully parsed, therefore the assignment to the factorial
variable is not yet complete, therefore the declaration of the variable is not yet valid. If you like, for the JSLint parser, it’s complete when the terminating semi-colon is reached. (For the compiler at run-time, there’s no issue: the code is compiled and valid way before it’s run.)
If I change the code to this more-verbose version instead:
var factorial;
factorial = function (value) {
"use strict";
if (value === 1) {
return 1;
}
return value * factorial(value - 1);
};
…there’s no issue since factorial
has been declared (even though technically it’s undefined
). Similarly, if I use a function statement instead:
function factorial(value) {
"use strict";
if (value === 1) {
return 1;
}
return value * factorial(value - 1);
}
…again there’s no issue, this time because by design JavaScript hoists function statements to the top of the scope.
There is however another way of doing this that resolves the problem and still allows my function expression preference. Ready?
var factorial = function callFactorial(value) {
"use strict";
if (value === 1) {
return 1;
}
return value * callFactorial(value - 1);
};
It turns out that callFactorial
is only visible in the inner scope of the function expression and not in the outer scope. In other words, I cannot use callFactorial()
to evaluate a factorial, I still have to use factorial()
. Since JSLint validates this code as perfectly sound, that was my solution to the problem. BOOM!
(Aside: a similar StackOverflow question.)
No Responses
Feel free to add a comment...
Leave a response
Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.
_emphasis_
**strong**
[text](url)
`IEnumerable`
* an item
1. an item
> Now is the time...
Preview of response