Global Domination

By YUI TeamJune 1st, 2006

JavaScript, as realized in browsers, is a load-and-go programming language. Programs are delivered to the execution site as text. This is a good fit for the web, which is at its root a text delivery system. The program text is eval‘d, which compiles it into an executable form and then immediately executes it. That execution can leave artifacts in the window’s global object.

The global object is the global namespace that holds the top level functions and global variables. Variables which are not explicitly defined are implied global variables, and their names are also kept in the global object. This was a convenience for the little scripts that Navigator 2 was expected to support. In the decade since NS2, those little scripts have grown into Ajax applications, and the true nature of the global object is revealed:

Global variables are evil.

Global variables are a source of unreliability and insecurity. Fortunately, JavaScript includes tools for allowing us to drastically minimize our use of globals, which makes our programs more robust. This becomes increasingly important as our programs get bigger, and as we mix in and mash up program components from multiple authors. Reducing our dependency on globals increases the likelihood that collisions are avoided and that the program components work harmoniously.

An objective measure of the quality of a JavaScript program is How many global variables and global functions does it have? A large number is bad because the chance of bad interactions with other programs goes up. Ideally, an application, library, component, or widget defines only a single global variable. That variable should be an object which contains and is the root namespace for all of your stuff.

Yahoo’s single global is YAHOO. It is spelled in all caps to identify it as something special, since all lower case is ordinary and initial caps indicates a constructor. Being in all caps, it is unlikely that someone would use it accidentally, which further reduces the likelihood of collision.

Yahoo is the world’s biggest website. Eventually, all of Yahoo’s JavaScript and browser webstate will be accessible through the YAHOO object.

But this technique also works well with the smallest library or widget. It is a clean, efficient way of organizing your program’s resources. The performance hit in having to access through a single global is negligible. JavaScript is very good at resolving such expressions. It is more than offset by the self-documentation and reliability benefits.

Generally a shallow tree is better than a deep tree. One could imagine that YAHOO.util.Dom.get could have been factored more compactly perhaps as YAHOO.get. And perhaps someday it will, but for now YAHOO.util.Dom.get is not measurably slower, and it is helping Yahoo to manage its evolving codebase. (And if you don’t like the length, you only have to type it once. See with Statement Considered Harmful.)

29 Comments

  1. Bravo for setting an example. Perhaps I can use this to prod my employer to move in a similar direction. Thanks!

  2. Theodor Zoulias said:
    June 1, 2006 at 3:00 pm

    I can’t agree less than 100%. Lots of global variables hanging around is one thing, and good quality JS code is another. And these two things rarely meet one another.

    I would like to read more about global namespace pollution via prototype extension of native JS objects (String, Array, etc). Isn’t it equally bad? And what should be said for some very popular JS libraries that are doing just that?

  3. Theodor Zoulias: Good point on the prototype extension of native objects. It’s conceivable that extending a string and/or some other object could potentially collide with another author’s extension of the same object.

    However, I also agree with the Douglas that through namespacing you can avoid similar situations as pertaining to your own code.

  4. [...] Global namespaces are a pain, and so is global domination;-) [...]

  5. > I can’t agree less than 100%

    What does that mean? Does that mean “you do agree more than 100%”? You disagree with less than whole?

    > Lots of global variables hanging around is one thing, and good quality JS code is another

    I’m not sure I fully understand that either. Indeed, lots of global variables is one thing, and quality code is another. When there is lots of global variables, then the quality of the code becomes bad (or is considered to not have as good of quality).

    Typically when working with YUI utils I like to set up the following shortcuts in my own private scope of my applications:

    MyApp.example = function() {
    var $E = YAHOO.util.Event;
    var $D = YAHOO.util.Dom;
    var $M = YAHOO.util.Motion;
    var $ = $D.get;
    return {
    init : function() {
    $E.on(['a','b','c'], 'click', this.fly, $('bar'), true);
    },
    fly : function() {
    var attributes = {
    width : { by : 50 },
    height : { by : 50 },
    points : { to : [100,200] }
    };
    var anim = new $A(this, attributes);
    anim.animate();
    }
    };
    }();

    The greatest part of it is that it allows me to have my own amount of verbosity. The lookups come at a very, very small price.

  6. Theodor Zoulias said:
    June 3, 2006 at 1:42 pm

    @Dustin Diaz:
    Ok, I needlessly made overly complex a simple phrase. I just wanted to express my total agreement with Mr Crockford’s arguments. :-)

    Your code snippet seems very elegant to me. But as far as I can understand your shortcut-using method makes your code faster, not slower. In other words the lookups come at a negative price I think.

  7. Indeed Theodor, they actually do come at a very small negative price. I actually don’t mind the extra time – they are literally unnoticeable, even in larger files. You can profile the extra weight over a thousand lookups and see for yourself that it’s very small.

  8. Good article — and I agree with Theodor:

    !(agreement

  9. Dustin Diaz,

    It is my understanding that variables starting with $ are intended for library code. Do you consider this a problem?

  10. peter michaux said:
    June 24, 2006 at 9:02 pm

    Matt,

    The ecmascript specs have something to say about the use of dollar sign.

    “The dollar sign ($) and the underscore (_) are permitted anywhere in an identifier. The dollar sign is intended for use only in mechanically generated code. ”

    http://www.ecma-international.org/publications/standards/Ecma-262.htm

    section 7.6

    According to this intention we are best not to start with $

  11. peter michaux said:
    June 24, 2006 at 9:05 pm

    I would like to see the middle namespace disappear in examples like YAHOO.util.Dom but I think it is worthwhile keeping YAHOO.Dom and not dropping the Dom.

  12. [...] Reasons why this sucks: 1) it’s ugly, and 2) it makes the code much less portable, because whoever adapts it will have to ferret out every instance of MINDSACK.foo and substitute his own namespace. I was just about to punt the whole namespacing idea, until I ran across another post by Mr. Diaz, this one a reply to Douglas Crockford’s Global Domination article on the YUIblog: Typically when working with YUI utils I like to set up the following shortcuts in my own private scope of my applications: [...]

  13. > Ideally, an application, library, component, or widget defines only a single global variable.

    Agreed, but how does it define the global variable?

    1: var YAHOO = {};
    2: YAHOO = {};
    3: window.YAHOO = {};
    4: self.YAHOO = {};

    I think #2 is the best way, but what is the reason for using #1 in YUI?

  14. I like #1 because it doesn’t look like an accident. I don’t like JavaScript’s implied global policy; I think it was a mistake. So I like all declarations, including global declarations, to be explicit.

  15. OK, but if I document it, then anyone can see it’s intentional:

    YAHOO = {}; //implied global

    I think the YAHOO’s declaration can be improved:

    switch( typeof YAHOO ) {
    case "undefined":
    var YAHOO = {};
    break;
    default:
    YAHOO = {}; //a proper re-definition
    }

  16. [...] Global variables are evil. Within YUI, we use only two globals: YAHOO and YAHOO_config. Everthing in YUI makes use of members within the YAHOO object hierarchy or variables that are scoped to such a member. We advise that you exercise similar discipline in your own applications, too. [...]

  17. [...] (When in doubt, wrap it in a closure. Global variables are evil.) [...]

  18. [...] doesn’t obfuscate global symbols, and 2) you won’t pollute the global object (see this great article by Douglas [...]

  19. [...] Global Domination, an article written by Douglas Crockford [...]

  20. >>OK, but if I document it, then anyone can see it’s intentional:

    Comments are not durable. I’ve known programmers who strip all comments upon opening a source file. The justification they give? “Comments are always wrong.” My translation of that is that code can be changed without changing the comments, so the comments don’t necessarily apply to the code that you see.

    Making the code clear enough that it doesn’t need comments is the best way to go.

  21. [...] 编写可重用的、优秀的JavaScript代码,其关键在于对名称空间的积极把控。JavaScript只拥有单一的、全局的名称空间(即window对象),而很多程序员(以及一些库)恣意地为之添加各种东西。要知道全局变量是魔鬼!聪明的开发人员,会使用类似组件模式的技术,来尽力减少全局对象的数量。 [...]

  22. [...] to use namespaces when writing your JavaScript. The reasons why have been stated time and again by much smarter and more eloquent people than myself, so suffice it to say, you should do [...]

  23. [...] call functions that are within the global namespace, and I try to avoid anything global for all the well-documented reasons.  I thought about using call() to change the invocation context, but setTimeout.call(object) will [...]

  24. The code sections are brilliantly elegant. Does the shortcut method actually make it faster or slower?

  25. Any idea if it is faster or slower? I might be a little inpatient, just wondering, thanks guys.

  26. [...] the number would be stored into variable result. Such a variable would be in the global scope, which is not a good idea. Even worse, although value would be retrievable once stored, we wouldn’t know when it [...]

  27. Hey, this is great when we get authorities like yahoo trend setting it helps us in getting our smaller and maybe more stubborn people to start to listen, thanks for the help!

  28. [...] thing that is evi in JavaScriptl. So are global variables, as detailed in Douglas Crockford’s Global Domination [...]

  29. [...] your code with others. For more details please take a look at Douglas Crockford’s artical at Yahoo! User Interface Blog (YUIBlog).To fix this we can wrap our code with a namespace. For example: someNamespace = { lang : 'en', [...]