Slight variation of the Revealing Module Pattern

59 views Asked by At

Is it good practice to use, instead of this Revealing Module Pattern ...

var MyModule = ( function() {
  function Method1() { alert( 'method1' ); }
  function Method2() { Method1(); alert( 'method2' ); }
  function Method3() { Method1(); alert( 'method3' ); }
  function Method4() { Method1(); alert( 'method4' ); }
  return { Method1 : Method1,    // these
           Method2 : Method2,    // lines
           Method3 : Method3,    // are 
           Method4 : Method4 };  // redundant...
} )();

MyModule.Method1(); 
MyModule.Method2();

... this slight variation:

var MyModule = {};
( function() {
  var Method1 = MyModule.Method1 = function () { alert( 'method1' ); };
  var Method2 = MyModule.Method2 = function () { Method1(); alert( 'method2' ); };
  var Method3 = MyModule.Method3 = function () { Method1(); alert( 'method3' ); };
  var Method4 = MyModule.Method4 = function () { Method1(); alert( 'method4' ); };
} )();

MyModule.Method1();
MyModule.Method2();

Is it 100% the same at the end? Would this considered as good practice?

3

There are 3 answers

1
Madara's Ghost On BEST ANSWER

It's not the same. If you were to rename your module at any time or wish to use it in a different name, you won't be able to.

Also, by returning the object at the end of the array, you make it perfectly clear what's exposed out of the object.

2
T.J. Crowder On

Is it 100% the same at the end?

The end result is the same.

Would this considered as good practice?

That's primarily a matter of opinion. Your examples are two of several variations on the RMP, both valid.

A third variation commonly seen is similar to your second, but has a specific purpose:

var MyModule = function(mod) {
  var Method1 = mod.Method1 = function () { alert( 'method1' ); };
  var Method2 = mod.Method2 = function () { Method1(); alert( 'method2' ); };
  var Method3 = mod.Method3 = function () { Method1(); alert( 'method3' ); };
  var Method4 = mod.Method4 = function () { Method1(); alert( 'method4' ); };
  return mod;
}(typeof MyModule === "undefined" ? {} : MyModule);

The purpose there is to allow adding to a module that's already defined, but creating it if it's not already defined.

1
I-Lin Kuo On

Your first and second variations are not the same. The first is what I would call a "self-contained" IIFE -- the body of the IIFE does its job without assuming any information about the world outside the IIFE. The second variation of yours assumes that there is a MyModule object in the outside world. While that is a small assumption, I prefer to write all my IIFEs in a self-contained manner.

The second variation can be made self-contained with a slight modification:

var MyModule = {};
( function(MyModule) {
  var Method1 = MyModule.Method1 = function () { alert( 'method1' ); };
  var Method2 = MyModule.Method2 = function () { Method1(); alert( 'method2' ); };
  var Method3 = MyModule.Method3 = function () { Method1(); alert( 'method3' ); };
  var Method4 = MyModule.Method4 = function () { Method1(); alert( 'method4' ); };
} )(MyModule);

MyModule.Method1();
MyModule.Method2();

By passing in the created external object as a parameter to the IIF, the code inside the IIFE no longer makes assumptions about the outside world, and can be more easily moved around to different places inside your code base.

However, you also asked

Would this be considered as good practice?

My answer to this is that you shouldn't use the Revealing Module Pattern at all! The Revealing Module Pattern has an important defect that makes me consider it an anti-pattern, so I would recommend against using it at all. Stick to the original module pattern, not the Revealing Module.