DEV Community

Discussion on: Revealing Module Pattern in Javascript

Collapse
 
peerreynders profile image
peerreynders • Edited

Just thinking out aloud ...

I was wondering what the difference between the module pattern and the revealing module pattern was.

Addy Osmani documented both in 2012 attributing the module pattern to Richard Cornford (2003) and the revealing module pattern to Chris Heilmann (2007).

Using an IIFE to create a closure that the object methods could use to share private data was already part of the "classic" module pattern:

// Classic Module Pattern
const counter = (function () {
  // private data
  let count = 0;

  return {
    increment() {
      count += 1;
    },
    twice() {
      // PROBLEM
      counter.increment();
      counter.increment();
    },
    current() {
      return count;
    },
  };
})();

console.assert(counter.current() === 0);
counter.increment();
console.assert(counter.current() === 1);
counter.twice();
console.assert(counter.current() === 3);
Enter fullscreen mode Exit fullscreen mode

The problem with the classic module pattern is that you have to use the outside variable (here counter) to reference a public method within any other object method.

One way to get around this is to use this:

// Classic Module Pattern
// with `this`
const counter = (function () {
  let count = 0;

  return {
    increment() {
      count += 1;
    },
    twice() {
      // quick fix: use `this`
      this.increment();
      this.increment();
    },
    current() {
      return count;
    },
  };
})();
Enter fullscreen mode Exit fullscreen mode

But around this time people were trying to avoid this as much as possible. So the revealing module pattern gets rid of intermediate references through the object by only using standalone functions that reference one another or shared data directly within the closure. Only those functions that are to be revealed to the public are attached as function values to the object literal that is returned.

// Revealing Module Pattern
// standalone functions - not object methods
const counter = (function () {
  let count = 0;

  return {
    increment,
    twice,
    current,
  };

  // function declarations
  // hoist automatically to the top
  function increment() {
    count += 1;
  }

  function twice() {
    // Just use function directly
    increment();
    increment();
  }

  function current() {
    return count;
  }
})();
Enter fullscreen mode Exit fullscreen mode

So the revealing module pattern isn't returning an object in the conventional sense but a "map" of non-method function values that access one another and shared data through the closure they were created in.

Just in case anybody was curious.

Collapse
 
pat_the99 profile image
Patricia Nicole Opetina

Wow thank you for this peerreynders!!

Collapse
 
peerreynders profile image
peerreynders

... come to think of it, as there is no reliance on this, the return value doesn't have to be an object anymore.

const initialValue = 0;
const valueTuple = (function (init) {
  let val = init;

  const getValue = () => val;
  const setValue = (newVal) => {
    val = newVal;
  };

  return [getValue, setValue];
})(initialValue);

const [current, set] = valueTuple;
console.assert(current() === initialValue, 'initialization failed');
set(1);
console.assert(current() === 1, 'set to 1 failed');
set(3);
console.assert(current() === 3, 'set to 3 failed');
Enter fullscreen mode Exit fullscreen mode

Though perhaps now we aren't revealing a "module" anymore.