Global Domination, Part Two

By Douglas CrockfordApril 16th, 2008

As I continue the practice of the craft of programming, I am always examining
my practices. Can I improve the patterns that I use so that I can make my
programs clearer, stronger, better? This is particularly important when working
with a language like JavaScript which has a bias that favors patterns that are
confusing, weak, and worse.

One of the worst features of JavaScript is its reliance on global variables.
This can be mitigated with global abatement and the module pattern, which can
significantly reduce the number of global variables that we need to declare.

But when we must declare a global variable, how best should we do that?
JavaScript provides three ways of declaring a global variable, and they all
have problems. Which is least worst?

The first is to assign to a new name outside of any function.

    pity = {};  // The first form

The second is to use the var keyword outside of any function.

    var pity = {};  // The second form

The third is to assign to a property of the global object.

    this.pity = {};  // The third form

All three forms do the same thing. (There is also a fourth way, the abominable
implied global, but we will not speak of that here. And don’t get me started on
the fifth and sixth ways.)

So, given three ways to do the same thing, which should we use? I used to favor
the second way. It looked to me the clearest in stating (or at least suggesting)
my intention to declare something.

But it wasn’t completely satisfactory. First, some people read var in that
position as declaring the variable in the scope of the compilation unit, similar
to the way static works in C. This would be a useful reading, except that
JavaScript does not have compilation unit scope. A knowledgeable programmer
should know that, but an alarming percentage of web developers program in
ignorance of the language, so this is a mild concern.

A greater concern is that the second form is larger than the first form,
but does the same thing. Generally, I prefer minimal forms.

But the thing that finally convinced me that the first form is the least worst
is that IE gets the second form wrong, so that responsibly adaptive programs
fail when using constructs like

    var pity = this.pity || {};

In order to be maximally productive, I want to avoid features that have
portability problems. It took me too long to accept that the second form is
problematic and should therefore be avoided.

The thing I liked about the second form was that it seemed more intentional.
By typing var, I declared that this isn’t an accidental misspelling. I am
intentionally declaring a new global variable. But JavaScript paid no attention.
I still feel the need to state that intention, so I state it in a comment.

    /*global pity*/
    pity = {};

JSLint is able to understand that comment, and can alert me to any global
variables that I did not intentionally declare. That gives me confidence that
I am not making a common mistake. The second form made me feel good, but didn’t
actually give me any real assurance.

I am still learning how to program. I read code, and I consider the opinions of
other programmers. I still have the capacity to change my practices. It is hard
sometimes to admit that my previous practices were weak. But that is more than
offset by adopting practices that are stronger.

Tagged as:

9 Comments

  1. Administrator said:
    April 21, 2008 at 3:22 am

    Testing the comment system, which was down for a while there. Everything seems back to normal, though, so give it a go!

  2. I would think that it is common knowledge to check typeof pity === 'undefined', instead of using a construct like var pity = this.pity || {};, especially assuming that the code in question is the byproduct of a reasonably adaptive program.

    If you assume that the web developer audiences that program in ignorance of the language and the readership of this blog (or the readership of any JavaScript blog author who adopts this method) are mutually exclusive, then one might trend towards agreeing your third form is appropriate.

    But, seeing that most developers “learn” from copy and paste, it would seem that the second form would be safer, if for no other reason than to prevent those abominable globals we all abhor.

  3. The “var pity = this.pity || {}” and it’s variants has become quite popular in recent Javascript libraries, and I like it myself. You’ll have to give in to the assumption that you use it in places where booleans are not values you expect.

    One of the most useful cases for me would be as a default value for function parameters. Consider:

    function doSomething (a) {
    a = a || ‘defaultValue’;
    }

    If the variable ‘a’ is undefined here, it will get a default value instead, making the variable ‘a’ useful to the rest of the function.

    Though if you prefer, I guess it could be written as:

    function doSomething (a) {
    a = (a !== undefined ? a : ‘defaultValue’);
    }

  4. [...] be lying if I said I wasn’t externally influenced on this one. Douglas Crockford has a lot of great recommendations, and this is one I tend to agree [...]

  5. Bernie Margolis said:
    November 19, 2008 at 3:24 pm

    I like how the ExtJS library handles this. They abstract developers away from the problem by providing a utility to create ‘namespaces.’ I don’t know how exactly they are doing it under the covers, but I know that Douglas Crockford’s javascript site is a heavy influence on their development, so I wouldn’t be surprised to find that they use one of the forms presented above. As a developer, though, all I have to do is this:
    Ext.namespace(‘pity’);
    or this shorter form:
    Ext.ns(‘pity’);
    I can even declare multiple levels on a single line:
    Ext.ns(‘pity’,’pity.util’, ‘pity.util.text’);

  6. another form that I usually prefer is:

    this.pity || (this.pity = {});

    the reason is it avoids an extra “same value” assignment if that global already exist and I do the same in functions for passed parameters:

    function doSomething (a) {
    a || (a = “defaultValue”);
    }

    good to spread the voice whatever the correct…

  7. Jay in Oregon said:
    July 12, 2010 at 10:57 am

    But the thing that finally convinced me that the first form is the least worst is that IE gets the second form wrong, so that responsibly adaptive programs fail

    I haven’t been able to find any information on how IE gets the second form wrong.

    Personally, I’ve been using:

    var fooObj;
    if (fooObj === undefined) {
    fooObj = {};
    }

  8. Don’t use the method described in the above article, if you know what’s good for you. Your code will break in ES-5 strict mode.

    Since undeclared assignments are such a misleading part of the language, ECMAScript 5 — newest version of ECMAScript — specifies that when they occur in a strict mode, a ReferenceError should be thrown. This makes for more robust code with less chance for unexpected errors. And since strict mode is more or less a future direction of the language, it makes sense to avoid undeclared assignments as if they never existed.

    http://perfectionkills.com/unnecessarily-comprehensive-look-into-a-rather-insignificant-issue-of-global-objects-creation/

  9. I recommend using only the function form of strict mode declaration. Zach’s comment only applies to the file form.