An Important Pair of Parens
Every single time I read code like the following it seems like someone has particularly gone out of his way to trick me and waste a little bit of my time.
var f = function() {
// function body code
// ...
// ...
}();
I happen to read code from top to bottom. You might too. When I see the first line above, I think "ok this functional literal is being assigned to f
." Then I proceed reading the function and investing energy thinking about the function and what it will do when f
is called. The trailing parens after the closing brace are the nasty little surprise waiting for me when I get to the bottom: after all that investment. That is when I learn that the function literal is not being assigned to f
but rather the function literal is being called and its return value (perhaps an integer, for example) is being assigned to f
. It would have been nice to have known this when I started reading the function. An early warning would be especially appreciated for functions over a screen long (perhaps many comments) where the trailing parens pair is not even visible without scrolling the page.
Yes I know I should always look first to see if the function is being automatically evaluated but normal assignment of a function literal is so much more common than automatic evaluation that it is a kneejerk reaction to assume it is a normal assignment. Habitual assumptions that things are normal are hard to break. (If someone changes your editor's key bindings how well can you type?)
I always write the above type of code like the following.
var f = (function(){
// function body code
// ...
// ...
})();
That extra opening paren before function
lets me know something unusual is happening. That little bit of extra info really helps when reading code top to bottom by giving the automatic execution of a function literal a little prefix syntax of its own. This is only a convention but a very appreciated one.
It turns out the extra set of parens are necessary when using automatic function execution for the module pattern. If an entire file is inside one of these anonymous functions the parens must be like the following.
(function() {
// function body code
// ...
// ...
})();
So it is more consistent to always uses the extra set of parens to indicate automatic execution and it will make your code less painful for others to read. Please, for the good of your code's readers, always include the extra pair of parens.
Comments
Have something to write? Comment on this article.
Good to know I'm not the only one who feels this way. It was also surprising to see Crockford following parenless style in his book.
Best,
kangax
Recently one of my friends pointed out that the version with extra parens blocks running it under Safari2.
slink,
I'm not sure what you mean by "blocks". I have never experienced a problem with Safari 2. Do you have a specific example?
I never seen the "blocks" either but would to take a look at them.
I would read code the same way you describe. Adding the extra parens before the function makes a lot of sense.
I agree, that reads much better now! I like your use of the extra parens.
Have something to write? Comment on this article.
Hello Peter,
I couldn't agree more! In fact, this is remotely related to namespaces in the following way.
I tend to use deep object-structures for namespaces instead of single object or prefix-namespaces. To deal with some of the problems that arise, I use a pair of functions namespace and using.
The 'namespace' function simply ensures the existence of one or more so-called package objects (i.e. the objects that represent the namespaces), for example
Ensures the existence of variable com which is an object with a property 'trifork', etc.
Now instead of writing, e.g., 'com.trifork.app.model.User = function(){...}' we can include or import package objects within a function with the 'using' function.
This runs the inner function with m bound to com.trifork.app.model.
Note that with this pattern neatly uses the module pattern, e.g., 'USER_TYPES' is a private variable to the User objects.
Now, and this is my point really, suppose you'd write
Then this is equivalent to:
except that when you read it you are not in doubt of whether the inner function is called or not. In fact, I've been using a specialized function 'inline' which does this, so you'd do:
While this is probably less performant, I would claim that it reads better.
Cheers,
- Karl