Object JavaScript – Namespaces, Anonymous Module, Revealing Module Pattern

10063_580983808600819_401360548_nUsing globals give you the opportunity to have your code overwritten by any other JavaScript added to the page after yours. And that is an opportunity best to be avoided.

The work around is to use the revealing module pattern.

I am a huge fan of the revealing module pattern. It keeps your objects encapsulates and was easier to understand for me as a C# guy.

In this post, we will step through the various JavaScript patterns and ending up at how you can implement the revealing module pattern. You will see the JavaScript syntax to create objects and how the revealing module patterns uses scope to keep private data private and reveals the data you want public. And you can do this without mucking up your globals.

Too Many of Globals

Globals are generally considered to be bad.

Global variable can potentially be modified from anywhere, (unless they reside in protected memory) and any part of the program may depend on it. A global variable therefore has an unlimited potential for creating mutual dependencies, and adding mutual dependencies increases complexity.

Let’s dive into some code. Here is some JavaScript code that you might find.

So what is the value of current? And what happens when you use a library that also has init() as a global function? And how easy is that to debug?

The problem is that access is not contained. Anything in the page can overwrite what you are doing.

Namespace Using Object Literal

A better approach is to place all of your code within a namespace; an object that contains all of your code. It helps to prevent name clashes with JavaScript code written by others.

You use literals to represent values in JavaScript. These are fixed values, not variables, that you literally provide in your script.

A simple example is like this:

var foo = {};
foo.name = "Spock";
foo.greeting = function() {
return "Hello " + foo.name;
}

Or you can use a different syntax, where you have declared the properties within the brackets.

var foo = {
  name: "Spock",
  greeting: function() {
    return "Hello " + foo.name;
  }
};

Either approach requires greeting refer to foo.name rather than just name.

But this repetition of the object name leads to huge code and is really annoying.

Using object literals, our code now looks like this:

my = {
    var current = null;
    var labels = [
    'home' : 'home',
    'articles' : 'articles',
    'contact':'contact'
  ];
  function init() {
  };
  function show() {
    my.current = 1;
  }
  function hide() {
    my.show();
  }
}

Anonymous Module

Another method of creating a namespace is through the use of a self executing function. Nothing is global.

(function() {
  var current = null;
  var labels = [
    'home' : 'home',
    'articles' : 'articles',
    'contact':'contact'
  ];
  function init() {
  };
  function show() {
    my.current = 1;
  }
  function hide() {
    my.show();
  }
})();

And while this code executes, there is now way to access it from the outside at all. So you cannot use callbacks or event handlers.

Module Pattern

You can specify what is global and what is not global. Use return keyword to specify what can be accessed from outside of the module.

What You Can Access (Public)

Assign the return value of an anonymous function to your namespace object.

myModule = function () {
  return {
    myPublicProperty: "I'm accessible as myModule.myPublicProperty.",
    myPublicMethod: function () {
    console.log("I'm accessible as myModule.myPublicMethod.");
    }
  };
}(); // the parens here cause the anonymous function to execute and return

The closing curly brace and then the parentheses () — this notation causes the anonymous function to execute immediately, returning the object containing myPublicProperty and myPublicMethod. As soon as the anonymous function returns, that returned object is addressable as myModule.

What You Cannot Access (Private)

Add “private” methods and variables in the anonymous function prior to the return statement.

myModule = function () {
   //"private" variables:
  var myPrivateVar = "I can be accessed only from within myModule.";

  //"private" method:
  var myPrivateMethod = function () {
      console.log("I can be accessed only from within myModule");
  }

  return {
    myPublicProperty: "I'm accessible as myModule.myPublicProperty.",
    myPublicMethod: function () {
      console.log("I'm accessible as myModule.myPublicMethod.");

    //Within myProject, I can access "private" vars and methods:
      console.log(myPrivateVar);
      console.log(myPrivateMethod());

      //The native scope of myPublicMethod is myProject; we can
      //access public members using "this":
      console.log(this.myPublicProperty);
    }
  };
}(); // the parens here cause the anonymous function to execute and return

In the preceding example, the myModule object you return  from an anonymous function is an object with two members. These members are addressable from within myModule as this.myPublicProperty and this.myPublicMethod. From outside of myModule, these public members are addressable as myModule.myPublicProperty and myModule.myPublicMethod.

The private variables myPrivateProperty and myPrivateMethod can only be accessed from within the anonymous function itself or from within a member of the returned object. They are preserved, despite the immediate execution and termination of the anonymous function, through the power of closure — the principle by which variables local to a function are retained after the function has returned. As long as myModule needs them, your two private variables will not be destroyed.

Revealing Module Pattern

You can make this easier to read using the Revealing Module Pattern. Here you put all of the functions, methods and variables above the return, and reveal the functions, methods, and variable you need following the return.

For example:

The public properties and methods are available because they are declared in the return. This also lets you keep the syntax consistent within your function.

References

Values, variables, and literals
Why is it bad to make elements global variables in Javascript? on Stackoverflow
Creating namespaces in JavaScript by Kevan Stannard
A JavaScript Module Pattern by Eric Miraglia
JavaScript Best Practices by Christian Heilmann
Spotting Outdated JavaScript by David B. Calhoun
Revealing Prototype Pattern – Techniques, Strategies and Patterns for Structuring JavaScript Code by Dan Wahlin

Advertisements

One comment

  1. Pingback: Object JavaScript – Revealing Modular Pattern Into Asynchronous Modules | DevDays®