Avoid Polluting The Global Namespace in JavaScript

In this blog post I will show how to avoid polluting the global namespace in JavaScript.

What is this namespace you speak of?

When we give our components names in our code, the interpreter adds them to a namespace. We can reference the component later by using that name. In a certain namespace, a we can only use certain name to reference, or point to, one thing (at a time).

The global namespace is a namespace that is common to all JavaScript code in your JavaScript interpreter. It’s also known as «global scope», and I use the terms loosely and interchangeably here, even though they mean different things.

The risk we are running by adding names to the global namespace, is that someone (or you) has already used that name elsewhere. This can result in a conflict. In the worst case you may break other code. In the best case, you will face a huge maintenance job of ensuring that there are none.

That’s why it is best if we all stay away from adding to the global namespace, and leave it for the core language names.

How do we go about and do that?

Anonymous function calls

An anonymous function is a function without a name. An anonymous function call, is an invocation of a function that doesn’t have a name. An anonymous function looks like this:

function () {
  var message = "Hello, World!";
  console.log(message);
}

We invoke this function by wrapping it in a pair of parenthesis:

(function () {
  var message = "Hello, World!";
  console.log(message);
})

and then adding a pair of parenthesis after it:

(function () {
  var message = "Hello, World!";
  console.log(message);
})();

For the purposes of this discussion, this is equivalent to:

var message = "Hello, World!";
console.log(message);

The difference is that in the encapsulated version the scope of the variable «message» is limited to that of the anonymous function, whereas in the non-encapsulated version, it is defined in the global namespace.

"use strict";

One thing we might want to put inside this function is an expression that is not about namespace pollution per se. But it is important enough to deserve a first-class seat in this post: "use strict";.

"use strict"; is a declaration that tells the interpreter to interpret the code in «strict mode».

So why don’t we just put "use strict"; at the top of our .js files and go have a piña colada?

The problem with declaring strict mode like this is that it may lead to inadvertent «strict mode» interpretation of other code, say, in a library that you have included in your project.

So, instead of declaring «strict mode» in the global namespace, do it inside an anonymous function call.

(function () {
  "use strict";
  var message = "Hello, World!";
  console.log(message);
})();

The «use strict» declaration applies to the code that follows the declaration itself. The strict interpretation will stop at the end of the function’s scope.

That was easy!

Unfortunately, things get a little more complicated when we start writing actual production code. In general, when we write an application, we don’t want to throw all our code into one place. Rather, we want to divide it into edible chunks, with well-defined interfaces. Moreover, we would like to put those chunks into their own files.

How can we do this without polluting the global namespace?

The short answer is: we can’t. But we can reduce the amount of pollution to a bare minimum.

A likely scenario is that you are using some sort of MVC framework. Since I am a big fan of Angular.js, and I am using it a lot in recent and current projects, I’ll use that as an example.

Angular.js

A typical «Hello World» example in Angular, might have a main.js file that looks something like this:

'use strict'

var app = angular.module('app', []);

var myController = app.controller('MyController', function ($scope) {
  $scope.message = "Hello, World!";
});

myController.directive('menu', function () {
  return {
    restrict: "A",
    templateUrl: "views/menu.html",
    controller: "NavigationController"
  };
});

I added a menu-directive for good measure, to illustrate a realistic amount of pollution. Let’s be nice citizens and do a little cleaning up:

(function () {
  'use strict';

  var app = angular.module('app', []);

  var myController = app.controller('MyController', function ($scope) {
    $scope.message = "Hello, World!";
  });

  myController.directive('menu', function () {
    return {
      restrict: "A",
      templateUrl: "views/menu.html",
      controller: "NavigationController"
    };
  });
})();

That’s better. We now have all that code inside an anomous function, restricting the scope of any names we add to the scope of that function.

But wait. What if we want to move our controller into its own file? We might go back to our first solution, and keep the name «app» in the global namespace, so we can refer to it elsewhere. Indeed, this is common practice in most examples of Angular.js I have seen.

Alas, there’s a better way.

You can retrieve a defined module at any time using the function angular.module().

Note the difference between

angular.module('app', []);

and

angular.module('app');

The first one register a new module with angular, with a set of dependencies (in this case, an empty set). The second one just retrieves the module that has already been registered.

So in my-controller.js, we do this:

(function () {
  'use strict';

  var app = angular.module('app');

  var myController = app.controller('MyController', function ($scope) {
    $scope.message = "Hello, World!";
  });

  myController.directive('menu', function () {
    return {
      restrict: "A",
      templateUrl: "views/menu.html",
      controller: "NavigationController"
    };
  });

})();

Incidentally, our main.js now only contains the module registration. Note that we don’t really need to assign the module to a variable any longer, but I kept it like this to make it clear: It’s scope is local to the anonymous function.

(function () {
  'use strict';
  var app = angular.module('app', []);
})();

Summary

I have shown a few ways to be a better citizen, and avoid polluting the global namespace in JavaScript. Do you have any other strategies? Do you think all this is unnecessary? Let us know!

2 kommentarer om “Avoid Polluting The Global Namespace in JavaScript”

Legg inn en kommentar