A useful JavaScript pattern – The Module Pattern

Introduction

A good API design forms an integral part of coding best practices. And what is a good API? A good API would only expose methods that would be needed by the client using the API. The public space would not be cluttered by unnecessary methods. And there are not many times where I have seen JavaScript developers really caring about a good API design. The reason probably is that people don’t take JavaScript seriously. Anyway, that is another topic, which might require a separate blog post of its own.

Module pattern

So coming back to the topic, I would be discussing a useful pattern that will help in achieving a good API design. This pattern is called module pattern.
This pattern allows you to hide helper methods and properties by declaring them as private, while public methods and properties are returned as the return value of an anonymous function that is executed immediately after its declaration.

Implementation

Consider you are creating an API for a gallery plugin, then following is how you would go about doing it using the module pattern, take special note of how we have not polluted the public space.

var My_gallery = function()
{
  //private properties
  var gallery;
  var item_container;
  var preview_img;
  var preview_caption;
  var num_items;

  // private methods
  var init_click_handlers = function()
  {
    item_container.find( 'li' ).click(function()
    {
      show_item( this );
    });
  }

  var preload_images = function()
  {
    item_container.find( 'img' ).each(function(index, element)
    {
      var img = new Image();
      img.src = $( element ).attr( 'large_src' );
    });
  }

  // return the public properties and methods
  return {
    init : function()
    {
      // public methods can call private properties directly
      gallery         = $( '#gallery_container' );
      item_container  = gallery.find( '#items' );
      preview_img     = gallery.find( '#preview_img' );
      preview_caption = gallery.find( '#preview_caption' );
      num_items       = item_container.find( 'li' ).length;

      // public methods can call private methods directly
      init_click_handlers();
      preload_images();
    },

    add_item : function(thumb_src, caption, large_src)
    {
      var new_item = gallery.find( 'li' ).first().clone();
      new_item.find( 'img' )
        .attr({
          src       : thumb_src,
          large_src : large_src,
          alt       : caption
        })
        .click(function()
        {
          // public method has to be called by its fully qualified name
          My_gallery.show_item( this );
        });

      gallery.find( 'li' ).append( new_item );
    }

    show_item : function( item )
    {
      preview_img.src( item.attr( 'large_src' );
      preview_caption.text( item.attr( 'alt' );
    }

    remove_item : function( item )
    {
      gallery.find( item ).empty();
    }

  }

}(); // this function is executed as soon as it is declared

The API of this plugin contains the following methods:

init();
add_item();
show_item();
remove_item();

See how we have called the function immediately after its declaration, this ensures that the methods returned are immediately added to the My_gallery object. An added advantage is that there are no global functions or properties, which means there would be no naming conflicts.

Typically these public methods would be called as follows:

$( window ).load(function()
{
  My_gallery.init();
  My_gallery.add_item( 'thumb.png', 'This is a really good image', 'large.png');
});

Conclusion

When using the module pattern, don’t return those too many methods, as that will pollute the public space, only return those that will be used by the client when calling the API. The public methods and properties have to be called by their fully qualified name, while the private methods and properties don’t require a fully qualified name, they have to be called by their names, since they are only available within the body of the anonymous function and are not visible outside.

You might want to take a look at one of my previous posts to learn more about the anonymous function trick.

  • http://www.collegegrantsweb.com college grants

    Valuable info. Lucky me I found your site by accident, I bookmarked it.

  • http://www.collegegrantsweb.com college grants

    Valuable info. Lucky me I found your site by accident, I bookmarked it.

  • cadet018

    This can easily be classified also as “how to write jquery plugin”.
    Good work indeed

  • cadet018

    This can easily be classified also as “how to write jquery plugin”.
    Good work indeed

  • http://tech.ovaistariq.net/ Ovais Tariq

    Yeah this pattern can be used for jquery plugin development, but I bet you would like to have a look here http://tech.ovaistariq.net/2010/07/extending-jquery-plugin-development/

  • http://tech.ovaistariq.net/ Ovais Tariq

    Yeah this pattern can be used for jquery plugin development, but I bet you would like to have a look here http://tech.ovaistariq.net/2010/07/extending-jquery-plugin-development/

  • Jordon Low

    A very useful pattern indeed

  • Jordon Low

    A very useful pattern indeed

  • http://nikehalftruth.blogspot.com/ zh_igor

    I would like to exchange links with your site tech.ovaistariq.net
    Is this possible?

  • http://nikehalftruth.blogspot.com/ zh_igor

    I would like to exchange links with your site tech.ovaistariq.net
    Is this possible?

  • http://www.kspace.in/blog Kunal

    Agree with this – “The reason probably is that people don’t take JavaScript seriously.”.

    BTW, a good tutorial on “How to use Module Pattern in Javascript”. Thanks

  • http://www.ovaistariq.net/ Ovais Tariq

    Yeah although JavaScript is really a very powerful language

  • MVCaraiman

    Very nice idea and very useful article.

  • http://www.ovaistariq.net/ Ovais Tariq

    Thank you mate.,

  • Umair655

    Nice article.

    I normally use following pattern to package my js properties and methods what I call js Class Pattern

    var class = {
    property: ‘test’,
    method: function() {}
    };

    Quite similar to yours.

  • http://www.ovaistariq.net/ Ovais Tariq

    that’s a nice way,.

blog comments powered by Disqus