First Chapters Free JavaScript Handbook JavaScript Design Patterns: JavaScript Patterns Unlocked: Module, Singleton, Factory, and More (Advanced Core JavaScript Mastery Series

JavaScript Design Patterns https://www.amazon.com/dp/B0DQXCGYX7 or https://www.amazon.ca/dp/B0DQXCGYX7

The JavaScript Handbook: Design Patterns is a comprehensive guide to understanding and mastering the essential design patterns that every developer needs. These patterns offer time-tested solutions to common programming challenges, making your code cleaner, more maintainable, and easier to scale.

This book is designed to take developers from foundational concepts to expert-level proficiency in JavaScript design patterns. You’ll learn how to implement and apply patterns like the Module, Singleton, Factory, Observer, and Prototype—all of which are essential for structuring and organizing modern applications.

What you will learn:

  • Module Pattern: Encapsulate your code, maintain private variables, and avoid polluting the global namespace.
  • Singleton Pattern: Ensure only one instance of an object exists, perfect for logging, configuration, and database connections.
  • Factory Pattern: Streamline object creation, especially when working with multiple object types.
  • Observer Pattern: Master event-driven programming, a key concept for UI development and reactive systems.
  • Prototype Pattern: Reuse methods across objects and take control of inheritance in JavaScript.

Each chapter includes detailed explanations, multiple-choice quizzes, coding exercises, and full solutions. These exercises help solidify your understanding and give you the confidence to recognize coding challenges, identify which pattern to apply, and refactor your code for clarity and maintainability.

Who is this book for? This book is ideal for:

  • Beginner developers who want a clear path to understanding design patterns.
  • Experienced developers looking to sharpen their skills and write cleaner, more modular code.
  • Web developers preparing for coding interviews, where knowledge of design patterns is essential.

Whether you’re looking to improve your problem-solving skills, prepare for interviews, or simply write better code, this book will guide you through everything you need to know about JavaScript Design Patterns. By the end, you’ll be able to spot and apply design patterns in your own applications, write cleaner code, and boost your development speed.

Introduction to the Module Pattern in JavaScript

What is the Module Pattern?

The module pattern is a design pattern used in JavaScript to encapsulate private and public data and methods. Before the advent of modern JavaScript module systems (like ES Modules or CommonJS), developers often used the module pattern to create self-contained units of code that kept internal details private while exposing a public API.

Why Use the Module Pattern?

  1. Encapsulation of Code: It helps you group related variables, functions, and functionality into a single unit.
  2. Preventing Global Pollution: The module pattern keeps variables and functions out of the global namespace, preventing naming collisions and promoting cleaner code.
  3. Data Privacy: By leveraging closures, you can create private variables and methods that cannot be accessed from the outside.
  4. Public API Exposure: It provides a controlled way to expose certain parts of the code to the outside world (the “public” methods) while keeping other parts hidden (“private” details).

How Does It Work?

The module pattern typically uses an Immediately Invoked Function Expression (IIFE). An IIFE is a function that runs immediately after it is defined. The structure looks like this:

var myModule = (function() {

    // Private variables and functions

    var privateVar = “I am private”;

    function privateMethod() {

        console.log(“This is a private method!”);

    }

    // Public methods and variables

    return {

        publicVar: “I am public”,

        publicMethod: function() {

            console.log(“This is a public method!”);

            console.log(“Accessing privateVar inside: ” + privateVar);

            privateMethod();

        }

    };

})();

In the snippet above, myModule holds the returned object, which contains publicVar and publicMethod. The variables and functions defined inside the IIFE but not returned remain private and inaccessible from the outside.

Key Concepts

IIFE (Immediately Invoked Function Expression):
An IIFE looks like this:
(function() {

    // code

})();

  1. The parentheses around the function definition ensure it’s treated as an expression, and the trailing () executes it immediately.
  2. Closures:
    The module pattern relies on closures. Variables defined in an outer function remain accessible to inner functions even after the outer function finishes execution. In the module pattern, the IIFE returns an object that can still access private data through closures, thus “closing over” the local variables.
  3. Private vs. Public Members:
    • Private: Declared inside the IIFE but not returned.
    • Public: Exposed as part of the returned object.

Benefits

  • Maintainability: Code is easier to read, maintain, and reuse.
  • Security: Private data is less prone to accidental modifications.
  • Namespace Management: Reduces global variable usage and prevents naming conflicts.

Drawbacks

  • Testing Private Members: Private functions and variables can be harder to test directly since they are hidden.
  • Refactoring Complexity: Breaking the code into multiple smaller modules may become cumbersome if you rely too heavily on a single large module.

Detailed Code Examples

Example 1: Simple Counter Module

var counterModule = (function() {

    var count = 0; // private variable

    function increment() {

        count++;

    }

    function decrement() {

        count–;

    }

    return {

        getCount: function() {

            return count;

        },

        increase: function() {

            increment();

            console.log(“Count after increment: ” + count);

        },

        decrease: function() {

            decrement();

            console.log(“Count after decrement: ” + count);

        }

    };

})();

// Usage

counterModule.increase(); // Count after increment: 1

counterModule.increase(); // Count after increment: 2

counterModule.decrease(); // Count after decrement: 1

console.log(counterModule.getCount()); // 1

// console.log(count); // Error: count is not defined globally

Example 2: Revealing Module Pattern

The “Revealing Module Pattern” is a variant that explicitly maps private members to public pointers, making it clearer which members are exposed.

var calculatorModule = (function() {

    var total = 0; // private

    function add(num) {

        total += num;

    }

    function subtract(num) {

        total -= num;

    }

    function reset() {

        total = 0;

    }

    function getTotal() {

        return total;

    }

    // Reveal only the methods we want to make public

    return {

        add: add,

        subtract: subtract,

        reset: reset,

        getTotal: getTotal

    };

})();

calculatorModule.add(10);

calculatorModule.subtract(3);

console.log(calculatorModule.getTotal()); // 7

calculatorModule.reset();

console.log(calculatorModule.getTotal()); // 0

Example 3: Namespaced Modules

You can create multiple modules under a single namespace:

var app = app || {};

app.moduleA = (function() {

    var privateMessage = “Hello from module A”;

    return {

        greet: function() {

            console.log(privateMessage);

        }

    };

})();

app.moduleB = (function() {

    var privateValue = 42;

    return {

        getValue: function() {

            return privateValue;

        }

    };

})();

app.moduleA.greet(); // Hello from module A

console.log(app.moduleB.getValue()); // 42


Multiple-Choice Questions

  1. Which best describes the Module Pattern in JavaScript?
    A. A pattern used to handle asynchronous code execution.
    B. A design pattern for organizing code into reusable classes.
    C. A pattern using closures and IIFEs to create private and public members.
    D. A pattern that removes the need for objects entirely.
    Answer: C.
    The module pattern relies on IIFEs and closures to encapsulate variables and functions, resulting in private and public members.
  2. What does IIFE stand for?
    A. Immediately Invoked Function Expression
    B. Internal Invoked Functional Execution
    C. Important Invoked Function Executor
    D. Immediately Integrated Function Expansion
    Answer: A.
    IIFE stands for Immediately Invoked Function Expression.
  3. Which of the following is a characteristic of an IIFE?
    A. It can never return a value.
    B. It is executed immediately after it’s defined.
    C. It must always be anonymous.
    D. It cannot contain private variables.
    Answer: B.
    An IIFE executes immediately as soon as it is defined.
  4. In the module pattern, what is the purpose of returning an object from the IIFE?
    A. To export public methods and properties.
    B. To ensure the function runs only once.
    C. To allow recursion within the module.
    D. To bind the module to the global window object.
    Answer: A.
    Returning an object exposes the public interface of the module.
  5. What can be considered a major benefit of the module pattern?
    A. Global scope pollution.
    B. Easily accessible private variables from outside.
    C. Encapsulation and avoiding namespace collisions.
    D. It prevents closures.
    Answer: C.
    The module pattern encapsulates code and avoids polluting the global scope.
  6. Which of these is NOT a disadvantage of the module pattern?
    A. Testing private members is harder.
    B. Potential complexity in refactoring large modules.
    C. Might require more memory usage than global variables.
    D. It prevents any public methods from being created.
    Answer: D.
    The module pattern does allow public methods; that’s the whole point of returning a public API.

In the following code, which is a private variable?
var myModule = (function() {

    var secret = “hidden”;

    return {

        reveal: function() { return secret; }

    };

})();

  1. A. myModule
    B. secret
    C. reveal
    D. (function() { … })
    Answer: B.
    secret is a private variable, accessible only inside the IIFE.
  2. Which of the following patterns is closely related to the module pattern and explicitly maps private members to public pointers?
    A. Singleton Pattern
    B. Constructor Pattern
    C. Revealing Module Pattern
    D. Prototype Pattern
    Answer: C.
    The Revealing Module Pattern explicitly returns an object literal mapping private members to public keys.
  3. How do closures help in the module pattern?
    A. By preventing variables from being garbage collected.
    B. By allowing inner functions to remember the environment in which they were created.
    C. By making all variables global.
    D. By preventing IIFEs from running automatically.
    Answer: B.
    Closures allow functions to retain access to their parent scope’s variables, enabling private data.
  4. Which is true about the module pattern and global variables?
    A. It encourages the use of many global variables.
    B. It completely eliminates global variables.
    C. It reduces the need for global variables, but typically one global reference is made for the module.
    D. It makes global variables automatically private.
    Answer: C.
    Usually, the module is assigned to a single global variable (e.g., var myModule = …), reducing global namespace pollution.
  5. The module pattern is often used in older JS codebases because:
    A. Modern bundlers and ES modules weren’t widely available in older environments.
    B. The module pattern is newer than ES modules.
    C. It is mandated by ECMAScript 6.
    D. It doesn’t rely on closures.
    Answer: A.
    Before ES Modules and bundlers became common, the module pattern was a popular way to create modular code.
  6. What happens if you do not return an object from the IIFE in the module pattern?
    A. You can’t have private variables anymore.
    B. You won’t have a public interface to access.
    C. The IIFE won’t run.
    D. An error is thrown at runtime.
    Answer: B.
    Without a returned object, no public methods or variables are exposed.
  7. Which keyword is not required to create a module pattern using IIFE?
    A. function
    B. return
    C. var or const to hold the module
    D. class
    Answer: D.
    The module pattern does not require the class keyword.

Consider this code:
var moduleX = (function() {

    var count = 0;

    return {

        inc: function() { count++; },

        get: function() { return count; }

    }

})();

moduleX.inc();

console.log(moduleX.get());

  1. What is logged to the console?
    A. undefined
    B. 0
    C. 1
    D. An error
    Answer: C.
    After one increment, count is 1, so console.log(moduleX.get()) prints 1.
  2. What is a key reason to use the module pattern?
    A. To immediately globalize every variable in the script.
    B. To manage and maintain code structure and data privacy.
    C. To replace all functions with classes.
    D. To ensure that variables persist across page reloads.
    Answer: B.
    The module pattern helps in organizing code and keeping data private.
  3. If you have a private function inside a module, how can you call it externally?
    A. Directly by its name.
    B. By exposing it through the returned object.
    C. By calling window.privateFunctionName().
    D. By converting it into an arrow function.
    Answer: B.
    To call it externally, you must expose it in the module’s returned object.
  4. Which symbol pair typically wraps the IIFE function definition?
    A. {}
    B. ()
    C. []
    D. <>
    Answer: B.
    IIFEs are wrapped in () both around the function expression and at the end to invoke it.
  5. In the module pattern, what does the returned object represent?
    A. The private variables.
    B. The public API of the module.
    C. The entire global namespace.
    D. Unused code.
    Answer: B.
    The returned object represents the public API that other code can use.
  6. The module pattern was heavily used before ES6 modules because:
    A. Browsers did not natively support module imports.
    B. It was the only pattern that worked in ES6.
    C. It is slower than ES modules.
    D. It required TypeScript.
    Answer: A.
    Before ES6, browsers didn’t support a native module system, so module pattern was a workaround.
  7. The IIFE in the module pattern is crucial because:
    A. It ensures that private variables are created anew every time the module is called.
    B. It prevents any variables from being created.
    C. It ensures immediate execution and creation of a closure.
    D. It forces the use of this keyword.
    Answer: C.
    The IIFE ensures the module’s code runs once and sets up closures to maintain private state.

10 Coding Exercises with Full Solutions and Explanations

Exercise 1: Basic Private and Public Methods

Task: Create a module mathModule that has a private variable pi = 3.14159 and two public methods: circumference(radius) and area(radius). circumference(radius) returns 2 * pi * radius, and area(radius) returns pi * radius * radius.

Solution:

var mathModule = (function() {

    var pi = 3.14159;

    function circumference(r) {

        return 2 * pi * r;

    }

    function area(r) {

        return pi * r * r;

    }

    return {

        circumference: circumference,

        area: area

    };

})();

// Explanation:

// pi is private. circumference and area are returned publicly, using pi internally.

console.log(mathModule.circumference(10)); // 62.8318

console.log(mathModule.area(10)); // 314.159

Exercise 2: Counter with Reset

Task: Create a module counter with a private variable count. Expose three public methods: increment(), decrement(), and current() that returns the current count. Also add a reset() method to set count back to 0.

Solution:

var counter = (function() {

    var count = 0;

    function increment() { count++; }

    function decrement() { count–; }

    function reset() { count = 0; }

    function current() { return count; }

    return {

        increment: increment,

        decrement: decrement,

        reset: reset,

        current: current

    };

})();

counter.increment();

counter.increment();

console.log(counter.current()); // 2

counter.reset();

console.log(counter.current()); // 0

Explanation:
The count variable is private. We provide a public API to manipulate and read it.

Exercise 3: Module with Private Helper Function

Task: Create a module stringModule that has a private function reverseString(str) and a public function isPalindrome(str) that uses reverseString to determine if a string is a palindrome.

Solution:

var stringModule = (function() {

    function reverseString(str) {

        return str.split(”).reverse().join(”);

    }

    function isPalindrome(str) {

        return str === reverseString(str);

    }

    return {

        isPalindrome: isPalindrome

    };

})();

console.log(stringModule.isPalindrome(“level”)); // true

console.log(stringModule.isPalindrome(“house”)); // false

Explanation:
reverseString is private and not accessible outside. isPalindrome uses it internally.

Exercise 4: Config Module

Task: Create a configModule that stores private configuration (like apiKey and apiUrl) and exposes methods getApiKey() and getApiUrl() to retrieve them.

Solution:

var configModule = (function() {

    var apiKey = “12345-abcde”;

    var apiUrl = “https://api.example.com”;

    function getApiKey() { return apiKey; }

    function getApiUrl() { return apiUrl; }

    return {

        getApiKey: getApiKey,

        getApiUrl: getApiUrl

    };

})();

console.log(configModule.getApiKey()); // “12345-abcde”

console.log(configModule.getApiUrl()); // “https://api.example.com”

Explanation:
Sensitive data like apiKey and apiUrl remain private. Only getters are exposed.

Exercise 5: Todo List Module

Task: Create a todoModule that stores a private array of todos. Public methods: add(todo), remove(index), and list() that returns all todos.

Solution:

var todoModule = (function() {

    var todos = [];

    function add(todo) {

        todos.push(todo);

    }

    function remove(index) {

        if (index >= 0 && index < todos.length) {

            todos.splice(index, 1);

        }

    }

    function list() {

        return todos.slice(); // return a copy

    }

    return {

        add: add,

        remove: remove,

        list: list

    };

})();

todoModule.add(“Learn JavaScript”);

todoModule.add(“Write Code”);

console.log(todoModule.list()); // [“Learn JavaScript”, “Write Code”]

todoModule.remove(0);

console.log(todoModule.list()); // [“Write Code”]

Explanation:
The todos array is not accessible externally, ensuring controlled manipulation.

Exercise 6: Bank Account Module

Task: Create a bankAccount module with a private balance variable. Public methods: deposit(amount), withdraw(amount), and getBalance().

Solution:

var bankAccount = (function() {

    var balance = 0;

    function deposit(amount) {

        if (amount > 0) balance += amount;

    }

    function withdraw(amount) {

        if (amount > 0 && amount <= balance) {

            balance -= amount;

        }

    }

    function getBalance() {

        return balance;

    }

    return {

        deposit: deposit,

        withdraw: withdraw,

        getBalance: getBalance

    };

})();

bankAccount.deposit(100);

bankAccount.withdraw(30);

console.log(bankAccount.getBalance()); // 70

Explanation:
Balance remains private to prevent unauthorized changes directly.

Exercise 7: Settings Module with Default Values

Task: Create a module settingsModule that has private variables for theme = “dark” and language = “en”. Public methods: setTheme(theme), getTheme(), setLanguage(lang), and getLanguage().

Solution:

var settingsModule = (function() {

    var theme = “dark”;

    var language = “en”;

    function setTheme(t) { theme = t; }

    function getTheme() { return theme; }

    function setLanguage(l) { language = l; }

    function getLanguage() { return language; }

    return {

        setTheme: setTheme,

        getTheme: getTheme,

        setLanguage: setLanguage,

        getLanguage: getLanguage

    };

})();

settingsModule.setTheme(“light”);

console.log(settingsModule.getTheme()); // “light”

console.log(settingsModule.getLanguage()); // “en”

Explanation:
The module encapsulates settings and provides controlled getters/setters.

Exercise 8: Memoization Module

Task: Create a fibModule that computes the nth Fibonacci number. Use a private cache object to store computed values. Public method: fib(n) that returns the nth Fibonacci number using memoization.

Solution:

var fibModule = (function() {

    var cache = {};

    function fib(n) {

        if (n < 2) return n;

        if (cache[n]) return cache[n];

        cache[n] = fib(n – 1) + fib(n – 2);

        return cache[n];

    }

    return {

        fib: fib

    };

})();

console.log(fibModule.fib(10)); // 55

Explanation:
cache is private. Each computed Fibonacci number is stored, making subsequent calls faster.

Exercise 9: User Authentication Module

Task: Create authModule that stores a private isLoggedIn boolean and username. Public methods: login(user), logout(), and status() that returns the username if logged in, otherwise “Not logged in”.

Solution:

var authModule = (function() {

    var isLoggedIn = false;

    var username = “”;

    function login(user) {

        isLoggedIn = true;

        username = user;

    }

    function logout() {

        isLoggedIn = false;

        username = “”;

    }

    function status() {

        return isLoggedIn ? “Logged in as ” + username : “Not logged in”;

    }

    return {

        login: login,

        logout: logout,

        status: status

    };

})();

authModule.login(“Alice”);

console.log(authModule.status()); // “Logged in as Alice”

authModule.logout();

console.log(authModule.status()); // “Not logged in”

Explanation:
isLoggedIn and username are private, preventing external code from tampering directly.

Exercise 10: Timer Module

Task: Create a timerModule that has a private variable startTime. Public methods: start(), stop(), which returns the elapsed time in milliseconds, and reset() which resets the timer.

Solution:

var timerModule = (function() {

    var startTime = null;

    function start() {

        startTime = Date.now();

    }

    function stop() {

        if (startTime === null) {

            return 0;

        }

        var elapsed = Date.now() – startTime;

        startTime = null;

        return elapsed;

    }

    function reset() {

        startTime = null;

    }

    return {

        start: start,

        stop: stop,

        reset: reset

    };

})();

timerModule.start();

setTimeout(function() {

    var elapsed = timerModule.stop();

    console.log(“Elapsed time: ” + elapsed + ” ms”);

}, 500);

Explanation:
startTime is private, and the public methods handle timing operations securely.


Conclusion

The Module Pattern in JavaScript is a powerful, pre-ES6 approach to structuring code, promoting encapsulation, protecting the global namespace, and clearly separating public APIs from private implementation details. By understanding and practicing with the pattern, developers gain insight into closures, scoping, and code organization techniques that remain useful, even in the era of modern ES modules.