The revealing module pattern is a variation of the module pattern in which  we declare ALL methods inside the function private scope, and we return an object with pointers to the methods that we want to make public.

Example of the traditional module pattern:

var ShoppingCart = (function () {

  var  items = [];

  return {
    addItem: function (a) {
      items.push(a);
    },
    removeItem: function (a)
    {
      items.splice(items.indexOf(a),1);
    }
  };
  })();

Same example using revealing module pattern:

var ShoppingCart = (function () {

  var  items = [];

   function  addItem(a) {
      items.push(a);
      console.log(items);
    }
    function removeItem(a)
    {
      items.splice(items.indexOf(a),1);
      console.log(items);
    }
  return {
    addItem:addItem,
    removeItem:removeItem
  };
  })();

As you can see when we use the revealing module pattern the public methods addItem, and removeItem are not implemented inside the return block, but in the function scope: they are private, but we expose them by returning an object that contains references pointing to those methods.

Why use the revealing module pattern?

At first sight the revealing module pattern appears to be a mere change in syntax, but if we dig deeper we will see that has some other implications: both for good, and ill.

Lets start with the most quoted reason that lead to the adoption of the revealing module pattern:

The Revealing Module pattern came about as Heilmann was frustrated with the fact that he had to repeat the name of the main object when we wanted to call one public method from another or access public variables.

We talk about this very point quite in detail in the article describing the drawbacks of the module pattern. As a brief remainder:when using the module pattern, if you try to call a public function from a public function you will run into a function is not defined error.

So this does not work:

var ShoppingCart = (function () {

  var  items = [];

  return {
    printShoppingCart: function(isVerbose)
    {
      console.log("printShoppingCart");
    },
    addItem: function (a) {
     printShoppingCart(false);
    }
  };
  })();

ShoppingCart.addItem("book");

And must be rewritten like this:

var ShoppingCart = (function () {

  var  items = [];

  return {
    printShoppingCart: function(isVerbose)
    {
      console.log("printShoppingCart");
    },
    addItem: function (a) {
     ShoppingCart.printShoppingCart(false);
    }
  };
  })();

ShoppingCart.addItem("book");

Notice that this issue only manifest itself when public functions call other public functions; calling private functions from public functions poses no problem whatsoever. Since in the revealing module pattern all functions are  implemented in the private scope, this issue is cleanly avoided.

Easily change visibility of the methods

Unlike the module pattern the revealing module pattern allows us to change the visibility of a method just by adding, or commenting a line:

var ShoppingCart = (function () {

  var  items = [];

  function printItemData(item)
    {
      console.log("printing data of product "+ item);
    }

   function  addItem(item) {
      items.push(item);
      printItemData(item)
      console.log(items);
    }
    function removeItem(item)
    {
      items.splice(items.indexOf(item),1);
      printItemData(item)
      console.log(items);
    }
  return {
    addItem:addItem,
    removeItem:removeItem
    //printItemData:printItemData
  };
  })();

In this example we can change the visibility of the method printItemData by commenting a single line, we do not need to make any changes whatsoever to the functions addItem and removeItem although both of them use printItemData.

Drawbacks in the revealing module pattern

Revealing pattern, or not revealing pattern we are still using a module pattern, and hiding access to some methods/variables. Which means we are going to run still in problems when it comes to patching or extending the module.

Actually, given that now all our functions are private, the problem is worse.

Let’s see some examples:

var Vehicle = (function () {

  var  model = "Toyota";

  function drive()
    {
      console.log("Driving a "+ model);
    }

  function travel(destination)
    {
      console.log("Picking my car to go to "+ destination);
      drive();
    }

  return {
    model:model,
    drive:drive,
    travel:travel
  };
  })();

Let’s update the model of the car:

Vehicle.model = "Nissan";
Vehicle.drive();

And the result is:

Driving a Toyota.

OK. It looks like I am still driving a Toyota, forget about Nissan.

Now let’s try to patch the drive function:

Vehicle.drive = function ()
{
  console.log("Drive fast");
}
Vehicle.drive();

So far the output is what we would expect:

Drive fast

But wait, what about the travel function?

Vehicle.travel("Florida");

Well, as you have probably guessed, we are not driving fast, but driving our trusty Toyota.

Picking my car to go to Florida
Driving a Toyota

Actually in this example we may have been slightly better off, using the plain module pattern:

// module pattern implementation
var Vehicle = (function () {
  return {
    model:"Toyota",
    drive:function()
    {
      console.log("Driving a "+ Vehicle.model);
    },
    travel:function (destination)
    {
      console.log("Picking my car to go to "+ destination);
      Vehicle.drive();
    }
  };
  })();

// Some usage examples
Vehicle.model = "Nissan";
Vehicle.drive();
Vehicle.drive = function ()
{
  console.log("Drive fast");
};
Vehicle.travel("Florida");

And the output:

Driving a Nissan
Picking my car to go to Florida
Drive fast
Advertisements