Christian Heilmann

Show love to the Module Pattern

Tuesday, July 24th, 2007 at 5:51 pm

Back in February 2006 I declared my love for the object literal explaining that it is a great way of making sure your scripts don’t interfere with others as all you expose to the world is a single object name. Instead of

function init(){}
function doStuff(){}
var myMessage = 'oi, gerrof!';

which might be easily overwritten you can use

myScript = {
  init:function(){}, 
  doStuff:function(){}, 
  myMessage:'oi, gerrof!'
}

and this way make sure that they don’t get overwritten or overwrite other methods or variables. You can access them as myScript.init(), myScript.doStuff() and myScript.myMessage. I liked this idea so much I argued for a length of time with my technical editor at that time that I want my book to be based on this kind of scripting or not at all.

The only annoyance I had with this is that it still leads to rather big methods, as you have to use the long name for every call of variables inside the object. True, you can use this, but when you use event handling and you don’t use the scope correction of the YUI event you’ll use that for the element the event occured on.

myScript = {
  init:function(){
    this.doStuff();
  }, 
  doStuff:function(){}, 
  myMessage:'oi, gerrof!'
}

Is therefore not necessarily possible, so you need to use:

myScript = {
  init:function(){
    myScript.doStuff();
  }, 
  doStuff:function(){}, 
  myMessage:'oi, gerrof!'
}

This, in much more complex scripts, can lead to a lot of code and typing (unless you use an IDE) and just seems bloated. I had a lot of problems fitting object literal scripts into 80 character code templates for the book and magazine articles for example.

The solution to shorter code is once again a thing from the mad JavaScript scientist’s lab of Douglas Crockford called the Module Pattern. If you want a very detailed and good explanation of what it does in terms of OO sorcery, check out the easy to follow explanation of the Module Pattern by Eric Miraglia on the YUI blog.

What the Module Pattern does for me on top of that is that it keeps my code short. I only expose those methods as public that need to be and then I can call them inside the main object by name of the method and not by objectname.methodname.

myScript = {
  massivelyLongVariableProbablyGerman:1,
  thisIsReallyLong:function(n){},
  doStuff:function(n){},
  init:function(){
    myScript.doStuff(myScript.massivelyLongVariableProbablyGerman);
    myScript.thisIsReallyLong(myScript.massivelyLongVariableProbablyGerman);
  }
}
myScript.init();

becomes

myScript = function(){
  var massivelyLongVariableProbablyGerman = 1;
  function thisIsReallyLong(n){};
  function doStuff(n){};
  return {
    init:function(){
      doStuff(massivelyLongVariableProbablyGerman);
      thisIsReallyLong(massivelyLongVariableProbablyGerman);
    }
  };
}();
myScript.init();

However, there are two problems remaining: if you want to call one public method from another public method you’d still need to go either via the this route or by prepending the main object name:

myScript = function(){
  var massivelyLongVariableProbablyGerman = 1;
  function thisIsReallyLong(n){};
  function doStuff(n){};
  return {
    init:function(){
      doStuff(massivelyLongVariableProbablyGerman);
      thisIsReallyLong(massivelyLongVariableProbablyGerman);
 
      otherPublic() // < - has MASSIVE FAIL! 
      this.otherPublic() // <- works 
      myScript.otherPublic() // <- works 
 
    },
    otherPublic:function(){
    }
  };
}();
myScript.init();</>

The other problem is that I am not too happy about the return {} with all the public methods in it, it still looks a bit alien to me. Caridy Patiño offered a solution to that problem on the YUIblog by simply creating an object with a short name inside the main object that can act as a shortcut for public methods to call each other:

var myScript = function(){
  var pub = {};
  var massivelyLongVariableProbablyGerman = 1;
  function thisIsReallyLong(n){};
  function doStuff(n){};
  pub.init = function(){
    doStuff(massivelyLongVariableProbablyGerman);
    thisIsReallyLong(massivelyLongVariableProbablyGerman);
    pub.otherPublic();
  };
  pub.otherPublic = function(){
  };
  return pub;
}();
myScript.init();

This also saves me one level of indentation which means I can fit even more code in 80 characters. I will use that much more in earnest now.

UPDATE

If you like what you see here, take it up another notch with the revealing module pattern

Share on Mastodon (needs instance)

Share on BlueSky

Newsletter

Check out the Dev Digest Newsletter I write every week for WeAreDevelopers. Latest issues:

160: Graphs and RAGs explained and VS Code extension hacks Graphs and RAG explained, how AI is reshaping UI and work, how to efficiently use Cursor, VS Code extensions security issues.
159: AI pipelines, 10x faster TypeScript, How to interview How to use LLMs to help you write code and how much electricity does that use? Is your API secure? 10x faster TypeScript thanks to Go!
158: 🕹️ Super Mario AI 🔑 API keys in LLMs 🤙🏾 Vibe Coding Why is AI playing Super Mario? How is hallucinating the least of our worries and what are rules for developing Safety Critical Code?
157: CUDA in Python, Gemini Code Assist and back-dooring LLMs We met with a CUDA expert from NVIDIA about the future of hardware, we look at how AI fails and how to play pong on 140 browser tabs.
156: Enterprise dead, all about Bluesky and React moves on! Learn about Bluesky as a platform, how to build a React App and how to speed up SQL. And play an impossible game in the browser.

My other work: