Revealing Modules and Mixins

6/5/14, updated 6/8/14

The revealing module pattern is the alternative to writing all your JS modules with prototypes. While prototypes have important benefits such as making methods available to all instances of an object, and chaining prototypes together, the revealing module pattern has it's own merits.

The part I like most about the revealing module pattern is the ease of separating private and public functionality via closure. I’d like to show how easy it can be to setup revealing modules while still being able to share functionality.

First, let’s take a look at the revealing module pattern:

      
  function Module () {
    var phrase = ‘Hello World’;

    function hello () {
      return phrase;
    };

    // the reveal
    return {
       hello: hello
    };
  };

  var module = Module();
  console.log(module.phrase);   // undefined
  console.log(module.hello());  // ‘Hello World'
      
    

Here we have a constructor that when called returns it’s public methods and properties with an object literal. In a slightly improved version, where namespacing is used to break up modules into different script files, our module might look more like this:

      
  (function (Namespace) {

    function MyModule () {
      var phrase = ‘Hello World’;

      function hello () {
        return phrase;
      };

      return {
         hello: hello
      };
    };

    Namespace.MyModule = MyModule;
  })(Namespace || {});

  var module = Namespace.Module();
      
    

Off to a great start! The only thing we need now is the ability to share functionality. An example of shared functionality I like to use is when I want event support for my objects. Here we’ll assume I have no library that provides event support. Without fully implementing the events module, I’ll outline the interface so you can see the end goal.

      
  function EventsMixin () {
    var events = {};

    function on (eventName, callback, context) {}
    function off (eventName) {}
    function trigger (eventName) {}

    return {
      on: on,
      off: off,
      trigger: trigger
    };
  }

  var events = EventsMixin();
  events.on(‘example’, function () {
   console.log(‘example event triggered’);
  });
  events.trigger(‘example’); // example event triggered
      
    

While the EventsMixin module is useful as a standalone event bus, I want to share the functionality with an instance of another module. A naive approach would be to write a simple extend method that will copy references from one object to another using a for...in loop.

      
  function extend(toBeExtended, extension) {
    for (var index in extension) {
      toBeExtended[index] = extension[index];
    }

    return toBeExtended;
  }

  var module = Module();
  var eventsMixin = EventsMixin();
  extend(module, eventsMixin);

  console.log(module.hello());        // Hello World
  console.log(typeof module.on);      // function
  console.log(typeof module.off);     // function
  console.log(typeof module.trigger); // function
      
    

This approach is not ideal, as we have to define what is mixed outside of our module creation, and we have to define an extend method. How can we make our implementation cleaner? We can return a function instead of an object literal from our mixin and use .call() to apply mixin properties onto our module.

I'll separate the implementation into two steps, starting with returning a function from our mixin:

      
  // our mixin updated to return a function
  function EventsMixin () {
    var events = {};

    function on (eventName, callback, context) {}
    function off (eventName) {}
    function trigger (eventName) {}

    return function () {
      this.on = on;
      this.off = off;
      this.trigger = trigger;

      return this;
    };
  }
      
    

Next, we just need to use the mixin on a module instance.

      
  // assume same events mixin from above

  function MyModule () {
    var phrase = ‘Hello World’;

    function hello () {
      return phrase;
    };

    return {
      hello: hello
    };
  }

  var module = MyModule();
  EventsMixin.call(module);

  // or, since our mixin returns 'this'
  var module = EventsMixin.call(MyModule());

  console.log(module.hello());        // Hello World
  console.log(typeof module.on);      // function
  console.log(typeof module.off);     // function
  console.log(typeof module.trigger); // function
      
    

Awesome right? Cleaner and more flexible. Now I have the ability to register events with any module instance. Keep in mind there are a number of ways to tweak this implementation by adjusting the way we define and initialize our modules. Check out these references to expand on this post.

Some Related References:

References used in this post:

I hope you enjoyed this tutorial and make good use of the module pattern as a result. I'll be following this up with another post on prototypes. Suggestions for improvments, questions, and comments are welcome.