notes

Log | Files | Refs | README

revealing_module_pattern.md (2492B)


      1 # Revealing Module Pattern in JavaScript
      2 
      3 The **revealing module pattern** wraps private state and behaviour inside a
      4 function (often an **IIFE**), then **returns a plain object** whose properties
      5 are the public API. Private helpers stay as inner functions or variables; only
      6 what you attach to that returned object is visible to callers.
      7 
      8 It is one variant of the classic **module pattern** from pre-ES2015 JavaScript,
      9 when files did not have native `import` / `export`.
     10 
     11 ## Shape
     12 
     13 ```js
     14 const counter = (function () {
     15   let count = 0 // private
     16 
     17   function increment() {
     18     count += 1
     19   }
     20 
     21   function getCount() {
     22     return count
     23   }
     24 
     25   return {
     26     increment,
     27     getCount,
     28   }
     29 })()
     30 
     31 counter.increment()
     32 console.log(counter.getCount()) // 1
     33 ```
     34 
     35 The **“revealing”** part is naming: you define real functions (`increment`,
     36 `getCount`) inside the closure, then **expose** them as properties on the
     37 returned object. Callers never see `count`; they only use the methods you
     38 listed.
     39 
     40 ## Why use it
     41 
     42 - **Encapsulation** — Private data is not a property on the returned object, so
     43   it cannot be read or overwritten from outside without going through your API.
     44 - **Stable surface** — The returned object is a small, explicit list of
     45   capabilities (sometimes called a **facade**).
     46 - **Refactoring room** — You can change how `increment` works internally without
     47   changing property names on the public object.
     48 
     49 ## Compared to ES modules
     50 
     51 Today, a file can achieve similar separation with **top-level private symbols**
     52 and explicit `export`:
     53 
     54 ```js
     55 let count = 0
     56 export function increment() {
     57   count += 1
     58 }
     59 export function getCount() {
     60   return count
     61 }
     62 ```
     63 
     64 The revealing module pattern remains useful when you need a **factory** (many
     65 independent instances), when bundling legacy scripts without a module loader, or
     66 when teaching how closures and object literals compose into a module-like API.
     67 
     68 ## Trade-offs
     69 
     70 - **Testing** — Private functions are hard to unit-test in isolation; you test
     71   through the public API or accept that internals are covered indirectly.
     72 - **Memory** — Each IIFE invocation creates new function instances; for many
     73   instances, consider whether a `class` or shared prototype fits better.
     74 
     75 ## References
     76 
     77 - [Addy Osmani — Essential JavaScript Design Patterns](https://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript)
     78 - [MDN — Closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures)