Search code examples
javascriptsyntaxiife

What is the "x = x || {}" technique in JavaScript - and how does it affect this IIFE?


First, a pseudo code example:

;(function(foo){

    foo.init = function(baz) { ... }

    foo.other = function() { ... }

    return foo;

}(window.FOO = window.FOO || {}));

Called like so:

FOO.init();

My question:

  • What is the technical name/description of: window.FOO = window.FOO || {}?

I understand what the code does... See below for my reason(s) for asking.


Reason for asking:

I'm calling the passed in global like so:

;(function(foo){
    ... foo vs. FOO, anyone else potentially confused? ...
}(window.FOO = window.FOO || {}));

... but I just don't like calling that lowercase "foo", considering that the global is called capitalized FOO... It just seems confusing.

If I knew the technical name of this technique, I could say:

;(function(technicalname){
    ... do something with technicalname, not to be confused with FOO ...
}(window.FOO = window.FOO || {}));

I've seen a recent (awesome) example where they called it "exports":

;(function(exports){
    ...
}(window.Lib = window.Lib || {}));

I guess I'm just trying to standardize my coding conventions... I'd like to learn what the pros do and how they think (that's why I'm asking here)!


Solution

  • Pattern
    (function (foo) {
        ...code...
        foo.bar = baz;
        ...more code...
    }(window.FOO = window.FOO || {});
    

    There is no formal name for the pattern you describe, because it's three separate patterns combined. Each pattern goes by multiple names, but for this post I will use the following terminology:

    • closure
    • alias
    • namespace extension

    Closure

    The base of the entire pattern is the closure. It is simply a function that is used to scope variables and functions such that they don't pollute the global namespace:

    No closure
    //these declare window.foo and window.bar respectively
    //as such, they pollute the global namespace
    var foo;
    function bar() {}
    
    Closure, in this case, an Immediately Invoked Functional Expression (IIFE)
    (function () {
        //these declare foo and bar within the function
        //but they are not accessible outside the function
        var foo;
        function bar() {}
    }());
    

    The advantage of keeping variables within a closure is that you won't have to worry about someone overwriting the variables that you're using. This is especially important for temporary variables such as i or j that are used often.

    Alias

    The second important part of this pattern is aliasing. Aliasing allows a variable to be defined and used within a closure without needing to worry about what global namespace it resides in.

    Without Aliasing
    (function () {
        ...
        foo = window.SomeFunction(bar, baz);
        ...
    }());
    
    With Aliasing
    (function (sf) { //local name
        ...
        foo = sf(bar, baz);
        ...
    }(window.SomeFunction)); //global namespace
    

    This is especially important as it means that the global namespace can be changed across a large JavaScript file by changing the name in a single location. This is A Good Thing™. Additionally, minifiers can shorten the internal alias to a single letter variable name such as a, making for significant byte savings on minification.

    Namespace Extension

    The namespace extension pattern relies on the coalescing behavior of the or operator (||). In many languages, && and || return either true or false, but in JavaScript, && returns the first falsey value (false, 0, '', null, undefined), and || returns the first truthy value (anything that's not falsey). For both operators, if the respective type is not found, the last argument is returned. This makes the || operator a convenient way of defining a new namespace only if it doesn't already exist.

    Without namespace extension
    if (typeof window.Foo === 'undefined') {
        window.foo = {};
    }
    
    With namespace extension
    window.foo = window.foo || {};
    

    This is useful because it allows a namespace to be extended with additional properties and methods without having to worry about which order the properties and methods were defined in.

    In this first example, FileA would need to be executed before FileB:

    FileA.js
    window.foo = {};
    window.foo.bar = 'baz';
    
    FileB.js
    window.foo.fizz = 'buzz';
    

    In this second example, File1 and File2 could be executed in any order:

    File1.js
    window.foo = window.foo || {};
    window.foo.bar = 'baz';
    
    File2.js
    window.foo = window.foo || {};
    window.foo.fizz = 'buzz';
    

    All together now

    Using each pattern together creates a very powerful modular script:

    //use foo internally so that you don't have to worry about
    //what the global namespace is called
    (function (foo) {
        //declare variables internally that you want to keep local to the script
        var i,
            len,
            internal,
            qux;
        //declare functions/properties on the alias when you want to expose them
        foo.bar = function () {...};
    //extend the global namespace so that existing extensions are persistent
    }(window.FOO = window.FOO || {}));