A couple colleagues have asked me about the ways things are arranged in Clumpy.js. So now that I’m sitting in bed, doped up on painkillers after having my wisdom teeth removed, it’s obviously the perfect time to write a blog post about JSLint, Douglas Crockford’s JavaScript Verifier Code Quality Tool.
The question was why I first declare the names of all my functions using var
, and then start assigning functions to them. This is a pattern I adopted about six months ago, before which JSLint had a long history of hurting my feelings whenever I wanted to do things like this:
var one;
function two () {
/* snip */
three();
}
function three () {
/* snip */
if (one) {
two();
}
}
It would tell me:
Problem at line 8 character 16: ‘three’ was used before it was defined.
And of course if I reversed the order of the functions, I’d get this:
Problem at line 10 character 14: ‘two’ was used before it was defined.
What’s a poor sap to do? I knew there was nothing wrong with recursive references like this, so I had always just ignored that warning. After all, I wasn’t trying to impress JSLint, I knew what I was doing, and that error message wasn’t really explained.
But whenever I find myself breaking rules that I don’t fully understand, I keep mulling it over until something clicks. Finally, I realized what JSLint was trying to tell me: Not that I couldn’t have two functions that used each other, but that I had to declare each one before I used a reference to it. So, I changed the above into this:
var one, two, three;
two = function () {
/* snip */
three();
};
three = function () {
/* snip */
if (one) {
two();
}
};
And with that, JSLint and I were ecstatic.
What I didn’t expect, though it seems obvious now, was how greatly this would improve the readability of my programs later, after I’d forgotten how they worked. In JavaScript, functions are just objects stored in regular variables, so it’s good to have all the declarations right there in one place.
And that’s just one of the many ways JSLint can improve your life. If you haven’t tried it, go do it now! This is the best advice you’ll get all day.
10 Responses
Thank you my friend. This drove me crazy. I just now found out the right way to declare the function handle before writing the implementation.
Thanks, this helped me out too! I couldn't figure out what was so bad about not having my functions declared in a certain (and impossible to reach) order.
Thanks for the awesome tip...i've been racking my brain trying to get my perfectly working scripts to validate with jslint haha
Thanks, this helped me get a better perspective on the JSLint error. I think I am going to restructure my code to use variable declarations like you describe here.
I disagree. I think what you are suggest might be useful, but you are in a sense tricking jslint.
Douglas Crockford says that he expects functions to be defined before they are used (note the function, not the variable)
Also newer functional languages such as f sharp also demand that functions are defined before they are used
Peter, what do you disagree with?
How would you suggest we go about writing two functions that recursively call each other? It is necessary for one function to be placed before the other in code; therefore, the invocation of one of the two functions must take place at a position in the file that is earlier than the position at which that function is defined.
How is it done in F Sharp?
Thomas,
Unfortunately, I don't know.
I came to this site looking for an answer to that very question
F sharp has a construction called "and" where you declare function a and function b joined by "and", thus informing the compiler that function a will recursively call function b and vice versa
However I haven't figured out how to deal with the (simpler) case you describe where function a needs to call function b and vice versa in a non recursive way
Perhaps you join both functions together using some higher order function.
If anyone has any ideas I would be grateful to hear them
I guess I was taking the meaning of recursive too literally. It looks like in f sharp a function marked as recursive does not have to call itself.
The code below does what we want, ie calling the f2 function before it is defined.
let rec f1 () =
printfn "in f1"
f2()
and f2 () =
printfn "in f2"
If you add a line at the end calling f1() from f2 it also works and forms and unending loop
But I don't know how to do the equivalent in javascript
Thanks. I didn't fully understand the issue until reading your post. Made it very clear.
Good stuff. Reading the post and the comments was very enlightening.