Writing modular JavaScript without polluting the global namespace
Marco Franssen /
6 min read • 1173 words
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 make 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 bullshit, 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 a 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.
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 seperate 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 you will 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?
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're 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.