Again with the Module Pattern – reveal something to the world

Wednesday, August 22nd, 2007 at 2:12 am

Not too long ago I was raving about the beauty of the Module Pattern in JavaScript and the annoyance I felt with it when it comes to repetition of long namespaces when calling or reading public methods and properties from other public methods and properties.

To recap, the “classic” Module Pattern means you define a variable as an anonymous function that gets immediately called with (). You define private functions and variables and return your public variables and functions as properties and methods of an anonymous object:

var classicModulePattern = function(){
  var privateVar = 1;
  function privateFunction(){
    alert('private');
  }
  return {
    publicVar:2,
    publicFunction:function(){
      classicModulePattern.anotherPublicFunction();   
    },
    anotherPublicFunction:function(){
      privateFunction();
    }
  }
}();
classicModulePattern.publicFunction();

The beef I had with that is that you need to repeat the name of the main object when you want to call one public method from another or access public variables. The other bit I was annoyed about is having to switch to object literal notation for the things you want to make public.

Inspired by the comments on the blog post on the YUI about the module pattern and pubstandards, I started advocating using a named object called pub to append methods and properties to before returning it. That way you can call public methods via the pub.methodName shortcut notation instead of repeating the main name:

var namedObjectModulePattern = function(){
  var pub = {};
  var privateVar = 1;
  function privateFunction(){
    alert('private');
  };
  pub.publicVar = 2;
  pub.publicFunction = function(){
  pub.anotherPublicFunction();    
  };
  pub.anotherPublicFunction = function(){
    privateFunction();
  };
  return pub;
}();
namedObjectModulePattern.publicFunction();

During a Q&A session in a training in Hongkong yesterday I showed this to Douglas Crockford and asked him what he thinks of it. He didn’t mind the idea, but considered even the pub object redundant.

There is another option which I am hereby calling the Revealing Module Pattern. In this permutation you simply define all your functions and variables in the private scope and return an anonymous object at the end of the module with pointers to the private variables and functions you want to reveal as public:

var revealingModulePattern = function(){
  var privateVar = 1;
  function privateFunction(){
    alert('private');
  };
  var publicVar = 2;
  function publicFunction(){
    anotherPublicFunction();    
  };
  function anotherPublicFunction(){
    privateFunction();
  };
  // reveal all things private by assigning public pointers
  return {
    publicFunction:publicFunction,
    publicVar:publicVar,
    anotherPublicFunction:anotherPublicFunction
  }
}();
revealingModulePattern.publicFunction();

This keeps the syntax of the whole script consistent and makes it obvious at the end which of the functions and variables can be accessed publicly. The other benefit is that you can reveal private functions with other, more specific names if you wanted to.

var revealingModulePattern = function(){
  var privateVar = 1;
  function privateFunction(){
    alert('private');
  };
  var publicVar = 2;
  function publicFunction(){
    anotherPublicFunction();    
  };
  function anotherPublicFunction(){
    privateFunction();
  };
  // reveal all things private by assigning public pointers
  return {
    init:publicFunction,
    count:publicVar,
    increase:anotherPublicFunction
  }
}();
revealingModulePattern.init();

You can even return values as the public properties by calling the functions in the anonymous object:

var revealingModulePattern = function(){
  var privateVar = 1;
  function privateFunction(){
    alert('private');
  };
  var publicVar = 2;
  function publicFunction(){
    anotherPublicFunction();    
  };
  function anotherPublicFunction(){
    privateFunction();
  };
  function getCurrentState(){
    return 2;
  };
  // reveal all things private by assigning public pointers
  return {
    init:publicFunction,
    count:publicVar,
    increase:anotherPublicFunction,
    current:getCurrentState()
  }
}();
alert(revealingModulePattern.current) 
// => 2
revealingModulePattern.init();

Of course the example names here are far from what I would use in a real script, but it shows the power of this pattern.

Share on Twitter