JavaScript Module Pattern or Just Private Variables

JavaScript is a wonderful language to get thinks fundamentally wrong from the start. As so where are many patters around to help us to avoid some of these challenges ;-).

The module pattern is one of the most known and used. It helps us to create private variables or better to avoid side effects in a larger JS application between the different JS files we load or frameworks we use.

The problem

Overall the problem is that in JavaScript everything is more or less public. Currently, most frameworks register their name in the Global space, also known as the window Object. You know them as angular or just $ or maybe even as Y.

Imagine the following code (jsBin):

// first JS file
var CLASS_NAME = "A1";
function A1() {}
A1.prototype.sayHallo = function() {
  $('#out').html(CLASS_NAME + ": says hallo!");
};

// second class in a different JS file
var CLASS_NAME = "B1";
function B1() {}
B1.prototype.sayHallo = function() {
  $('#out').html(CLASS_NAME + ": says hallo!");
};

// some code
$('#cmdA1').click(function() {
  new A1().sayHallo();
});
$('#cmdB1').click(function() {
  new B1().sayHallo();
});

It doesn’t matter which button you press the result will always be B1 because we have overwritten the value in CLASS_NAME in the second part.

Even if this sample is somehow of course constructed, this problem can easily happen in a larger JS application. We must take this into account an protect ourself.

The solution

The solution is pretty straight forward. We just wrap our class definition into an anonymous function. This does not only protect us but it allows us to create really private variables in JS which can’t be overwritten from outside — we can protect the access to them with functions.

jsBin again

// first JS file
MyGlobal = {};
(function($) {
  var CLASS_NAME = "A1";
  function A1() {}
  A1.prototype.sayHallo = function() {
    $('#out').html(CLASS_NAME + ": says hallo!");
  };
  MyGlobal.A1 = A1;
})(window.$); // pass any global scope

// second class in a different JS file
(function($) {
  var CLASS_NAME = "B1";
  function B1() {}
  B1.prototype.sayHallo = function() {
    $('#out').html(CLASS_NAME + ": says hallo!");
  };
  MyGlobal.B1 = B1;
})(window.$);

// some code
$('#cmdA1').click(function() {
  new MyGlobal.A1().sayHallo();
});
$('#cmdB1').click(function() {
  new MyGlobal.B1().sayHallo();
});

What have we learned?

  • In JavaScript, the best practice is to wrap our code into anonymous functions
  • Define one global scope variable which we use to register all our classes (here MyGlobal)
  • Anonymous function also allow us to create private/ protected variables

Paul Sterl has written 55 articles

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>