JavaScript Namespaces and Closures instead of Global Variables

Have you heard? Global variables are bad, mmkay? So what should we do if we want to create a variable in our script and be able to refer to it elsewhere, globally?

What's in a Namespace?

A JavaScript namespace is just an idea or practice rather than an explicit feature of JavaScript. That is, you don't create a "namespace object" or declare a namespace. Instead, you would implement a namespace by creating and using an object which would contain sub-variables within it, so that those variables didn't pollute the namespace of the global scope (i.e. everything under the window object in the JavaScript DOM).

var aNamespace = {};
aNamespace.aVar = 'A public variable';
aNamespace.getAVar = function () { return aNamespace.aVar; };

Why do we need this? As JavaScript scripts get bigger, as they include more 3rd party libraries, there is more chance for variable naming conflicts. Creating variables inside a namespace reduces the possibility of conflict to just the name of the namespaces colliding, which can happen with libraries which use the $ variable such as jQuery. If you're using jQuery and another library at the same time which defines $ for its own use, then your code needs to be able to refer to the correct $ object depending on where it's called. The solution is to create an enclosing function around your jQuery code, passing jQuery in as a local variable $, e.g.

(function($){
  // now $ is a local variable, not the global one
  $('#foo').bar();
  $('.bar').baz();
  $('#foo .bar').show();
})(jQuery);

This example doesn't demonstrate namespaces, besides jQuery being a namespace, but shows how variable scoping inside functions can be used to separate or protect a variable in the global scope.

Closures returning namespaces

In the first example, we showed a simple namespace which demonstrated variables and methods (which is just a function in a namespace, there's no other distinction within JavaScript). A namespace's variables and functions can be defined when the namespace is defined or added to the namespace afterwards. But what if we have a lot of variables, including only internally-used ones, and member functions which are just helpers and don't need to be used outside the namespace? This is where we want both private and public members. But JavaScript has no private or public keywords! The concept, like namespaces, doesn't exist as a native language feature of JavaScript. But we can still use normal JS objects to implement private properties.

var aNamespace = (function () {
  var aPrivateVar = 'This is private and cannot be accessed directly';
  return {
    aPublicVar: 'This can be accessed directly',
    getPrivate: function () { return aPrivateVar; },
    setPrivate: function (v) { aPrivateVar = v; }
  }
})();

This code (1) creates a namespace, (2) creates a closure around private variables in the namespace (by returning a reference to a function which references a variable defined in the scope where the function was defined thus forcing the variable to remain accessible by that function when that function is called even when execution is outside the parent), (3) creates an anonymous function which returns the namespace object and then immediately calls the anonymous function to return the object to set aNamespace to it.

There is also the convention of using underscores before property names to have them be considered private instead of public but doesn't actually offer any protection unlike the above closure pattern which doesn't provide any backdoor way to access the private members.

Add new comment