May 2009 Archives

Proposed coding convention for closures

| 6 Comments

By now, many of us have gotten used to using closures in JavaScript to define a scope that holds private variables and utility functions so that we don't have to put these in the global namespace. The idiomatic code looks like this:

(function() {
      var private_var;    // Visible only inside this function
      function helper_function() { ... }
      
      // export an object or function to the global namespace
})();  // Invoke the outer function

The outer function exists only to create a scope to hold our internal variables. It has no name and is invoked exactly once, immediately after being defined. The fact that this is a function expression (rather than a statement-like function declaration) means that we can invoke it immediately after defining it. The parentheses before the function keyword and after the closing } are required because otherwise the JavaScript interpreter would think that this was a function declaration and would complain about the missing function name.

That unusual opening parenthesis before "function" serves another important purpose in this idiom. It alerts us to the fact that this function is being used idiomatically, that it exists solely to create a scope and that it is going to be invoked immediately.

So far, so good. But I've finally gotten around to reading Douglas Crockford's JavaScript: The Good Parts and it has made me think that an additional explicit naming convention would be helpful. (As an aside, Crockford's short book is worth a read, though I find that I disagree with some of his coding conventions. I'm tempted to write a review titled "JavaScript: The Good Parts: The Good Parts"...)

When the function keyword is the first token in a new JavaScript statement, the interpreter expects to see a function declaration, not a function expression. That's why we needed the idiomatic parentheses in the code above. But when the function keyword is used as part of an assignment or as an argument to some other function, those parentheses are not required. Crockford's book includes code like this (page 37):

var myObject = function() {
    var value = 0;

    return { // 7 lines of code omitted here
    };
}();

When I first read the assignment statement it appears to me (despite the name of the variable) that it is a function value being assigned. In fact, however, the function is merely there to establish a scope for private variables. The function is invoked as soon as it is defined, and it is the return value of the function that is assigned. The problem is that I don't realize this until I read all the way down to the end of the function. Appendix E takes this to an extreme. The code begins:

var json_parse = function() {

It looks like we're creating a function and assigning it to the variable json_parse. But five pages later we see:

}();

Now we realize that the value assigned to json_parse is not the function we thought it was, but the function returned by that function.

Another example appears on page 40:

String.method('deentityify', function() {
   // 25 lines omitted
}());

It appears at first that we're passing a function as the second argument of the invocation of String.method. It is not 'till we read all the way through this function that we realize that we're passing the result of invoking the function.

So, how can this code be improved? One way would be to use the idiomatic parentheses around function expressions that are going to be immediately invoked even when they are not necessary. That would turn the code above into this:

String.method('deentityify', (function() {
   // 25 lines omitted
})());

I think that would be helpful, but I think we can do better. Function expressions are allowed to have names, and those names are only visible within the body of the function (allowing such a function to invoke itself recursively, for example). So let's say that when we're going to define a function for the purpose of creating a scope we make that explicit by giving it a dummy name like "scope" or "closure" or "invocation". This results in code like:

var myObject = function scope() {
   // code omitted
}();

String.method('deentityify', function invocation() {
   // 25 lines omitted
}());

Your thoughts are welcome in the comments. Has anyone else proposed a convention like this? What's the best name to use for these functions?

Update: I suppose we could also simply adopt a comment-based convention:

var myObject = /* return value of */ function () {
   // code omitted
}();

String.method('deentityify', /* result of */ function() {
   // 25 lines omitted
}());

Update 2: It turns out that Douglas Crockford is about 2 months ahead of me. In March he updated jslint to (optionally) issue warnings about immediate invocation of function expressions unless the entire invocation appears in parentheses, and also to warn if a function is parenthesized and is not immediately invoked. So Crockford's convention looks like the following:

var myObject = (function () {
   // code omitted
}());

String.method('deentityify', (function() {
   // 25 lines omitted
}()));

Note that Crockford wraps the invocation in parens, not just the function. That is, he uses ()) at the end instead of (the more commonly used) )(). He has said that he'll update his book to follow these conventions in the next printing.

Books

ECMAScript 5 & HTML5!

"A must-have reference"
Brendan Eich,
creator of JavaScript

JavaScript graphics makes web programming fun again!

Read Less, Learn More

Comprehensive coverage of Ruby 1.8 and 1.9

"The New Most Important Ruby Book"
Peter Cooper,
rubyinside.com

The classic Java quick-reference

About

Advertising

Pages

Hosted By

Powered by Movable Type 4.21-en