Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Writing Modular JavaScript Without Polluting the Global Namespace

2.00/5 (1 vote)
12 Mar 2012CPOL4 min read 21.3K  
How to write modular JavaScript without polluting the global namespace

Most of you have already seen a lot of spaghetti JavaScript code. One of the reasons you are reading this article will probably be, you don’t want to make the same mistakes as others have done. So let’s do the next step and stop polluting the global JavaScript namespace.

Why is it bad to have all your script code available at global level?

First of all, you can possibly get a lot of errors when using modules developed by others, because you used the same names for you variables, etc.

The second reason is, this code can’t be minified as good as the code I will show you later.

The third reason is, you are not forcing yourself well enough to write some clean JavaScript.

If you think I’m talking bullsh*t, you can better stop reading this article and continue giving JavaScript a bad name and scare of other developers with spaghetti code.

First of all, we need to learn to write a JavaScript module. There are a lot of examples how to achieve this. This article is an in-depth description of the module pattern. Another well know example is the object literal pattern.

In my example, I will use a pattern like in the first article because it will allow me to control visibility.

JavaScript
var shoppingCart = (function() {
    var items = [];
    var priceTotal = 0;

    var addProduct = function(product) {
        items.push(product);
        updatePriceTotal();
    };

    var removeProduct = function(product) {
        //remove product from items
        updatePriceTotal();
    };

    var updatePriceTotal = function() {
        //logic to update the priceTotal
        //use public functions on product to get the price of products
    };
    
    return {
        addProduct: addProduct,
        removeProduct: removeProduct 
    }
}());

As you can see, I use a very bare example, which is just enough to show you my point. We see we put all our JavaScript modules into a separate file, which is really helpful when you need to maintain them. In the shoppingCart, I gave you an example how to control visibility. The ‘updatePriceTotal’ function will be private within the module.

This way of writing your code looks pretty much like writing your code in C# or Java, isn’t it (except from the syntax).

But we are still polluting the global namespace. Now there are only two variables, but think of it when you complete the code I started. How many modules would be added? How much more will you be polluting the global namespace?

When opening the developer tools in for example Chrome and hitting F12 and navigating to the console tab and you type ‘product’ or ‘shoppingCart’ and hit the enter key, you can access the objects from the global namespace.

So how can we wrap these modules in our own namespace?

JavaScript
; (function(jsShop, window, document, undefined) {
    var product = jsShop.product;
    var shoppingCart = jsShop.shoppingCart = jsShop.shoppingCart || (function() {
        var items = [];
        var priceTotal = 0;
    
        var addProduct = function(product) {
            items.push(product);
            updatePriceTotal();
        };
    
        var removeProduct = function(product) {
            //remove product from items
            updatePriceTotal();
        };

        var updatePriceTotal = function() {
            //logic to update the priceTotal
            //use public functions on product to get the price of products
        };
        
        return {
            addProduct: addProduct,
            removeProduct: removeProduct 
        }
    }());
}(window._jsShop = window._jsShop || {}, window, document));

As you can see, we build a little wrapper around our modules. This wrapper is a self executing function which provides access to the elements from the global namespace. When calling this anonymous self executing function, we provide our own namespace which we register at global level. We also provide window, document and undefined, because this gives advantages in performance and minification of your scripts. When you never use them in your script, you don’t need to add them, but as a best practice, I always add them so I will never forget them. Please note that the last parameter isn’t provided, so it is undefined.

Another best practice is to start each script with a semicolon, so you don’t have to bother about missing semicolons in other scripts. By starting with one at least this script file will not give errors on behalf of missing semicolons in other files. Issues most of the time occur when minifying your scripts.

Last but not least, we have to register our module in our namespace. What we do is checking if the module already exists or else replace it with your module definition.

You may be asking, what if I want to use jQuery or whatever other script? Just add it to the wrapper so you can use it in you module.

Now we have achieved ‘product’ and ‘shoppingCart’ are not polluting the global namespace anymore. As you may already have noticed, I used an _ in my namespace just to give a little bit more insurance it isn’t used by another external JavaScript. You can test this by opening the developer tools in for example Chrome and hitting F12. Try it out by typing '_jsShop' and hitting Enter, you should see everything registered in the _jsShop namespace. Google Analytics for example uses the same naming conventions. They are using the _gac variable to provide you access to their API.

If you want to read more about JavaScript namespacing, you should read this article. In this example, I used one of the preferred patterns of Addy Osmani.

By writing your JavaScript like I described above, it will be very easy to use require.js to load your JavaScript dependencies asynchronously. For now, see Addy Osmani’s article about AMD (Asynchronous Module Definition) to make the next step, until I finished my own, step by step article, which will proceed where I stopped in this article.

Also, have a look at my jQuery events contributes to clean Javascript article, for a deeper dive into JavaScript modules working with events and jQuery. Note I didn’t use proper name-spacing here, but you know how to add it now.

Hope you enjoyed this article and we can build together on better JavaScript code. Share it with your friends and colleagues and give me some feedback so I can learn from you.

As a last advice…

Subscribe to Addy Osmani’s RSS Feed.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)