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)