JavaScript Module Pattern


What is the Module Pattern in JavaScript?

The Module Pattern is a design pattern used to encapsulate private variables and functions within a closure, exposing only a public API. This helps to avoid polluting the global scope and provides better organization of code.


How do you create a simple module using the Module Pattern?

You can create a module by defining an IIFE (Immediately Invoked Function Expression) that returns an object containing public methods and properties.


const MyModule = (function() {
  let privateVariable = 'I am private';

  function privateMethod() {
    console.log(privateVariable);
  }

  return {
    publicMethod: function() {
      privateMethod();
    },
    setPrivateVariable: function(value) {
      privateVariable = value; // Exposing a way to modify the private variable
    }
  };
})();

MyModule.publicMethod(); // Outputs: I am private
MyModule.setPrivateVariable('New Value');
MyModule.publicMethod(); // Outputs: New Value

What are the advantages of using the Module Pattern?

Advantages of the Module Pattern include:

  • Encapsulation: It allows you to bundle related functions and variables together while hiding the implementation details.
  • Reduced Global Scope Pollution: It helps to avoid adding variables to the global scope, minimizing potential naming conflicts.
  • Improved Code Organization: Modules promote better organization and separation of concerns, making the codebase easier to understand and maintain.
  • Private Variables: The pattern provides a way to create private variables and methods that cannot be accessed directly from outside the module.

How do you create a singleton module using the Module Pattern?

A singleton module ensures that only one instance of the module exists. This can be achieved by returning the module from the IIFE.


const SingletonModule = (function() {
  let instance;

  function createInstance() {
    return { name: 'Singleton Instance' };
  }

  return {
    getInstance: function() {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    }
  };
})();

const instance1 = SingletonModule.getInstance();
const instance2 = SingletonModule.getInstance();
console.log(instance1 === instance2); // true (Both references point to the same instance)

Can you demonstrate the use of private methods in the Module Pattern?

Private methods can be created within the module and accessed only through public methods, ensuring they cannot be called directly from outside the module.


const CounterModule = (function() {
  let count = 0; // Private variable

  function privateIncrement() {
    count++;
  }

  return {
    increment: function() {
      privateIncrement();
      console.log(count);
    },
    reset: function() {
      count = 0;
    }
  };
})();

CounterModule.increment(); // 1
CounterModule.increment(); // 2
CounterModule.reset();
CounterModule.increment(); // 1
// console.log(CounterModule.count); // Undefined (private variable)

How does the Module Pattern facilitate dependency management?

The Module Pattern can facilitate dependency management by allowing modules to depend on other modules. You can pass dependencies as parameters to the module, which can then use them internally.


const LoggerModule = (function() {
  return {
    log: function(message) {
      console.log(message);
    }
  };
})();

const AppModule = (function(Logger) {
  return {
    run: function() {
      Logger.log('App is running!');
    }
  };
})(LoggerModule);

AppModule.run(); // App is running!

What are the limitations of the Module Pattern?

Some limitations of the Module Pattern include:

  • Less Flexibility: Once the module is created, adding new methods or properties can be challenging without modifying the original module code.
  • Overhead: The use of IIFE can add a slight overhead in terms of performance due to the creation of a new scope.
  • Global Access: If the module is not designed correctly, it might expose more than intended, defeating the purpose of encapsulation.

How can you extend the Module Pattern?

You can extend the Module Pattern by returning additional methods or properties in the returned object, or by combining it with other design patterns like the Factory or Observer patterns.


const ExtendedModule = (function() {
  let privateVariable = 'I am private';

  function privateMethod() {
    console.log(privateVariable);
  }

  return {
    publicMethod: function() {
      privateMethod();
    },
    setPrivateVariable: function(value) {
      privateVariable = value;
    },
    additionalMethod: function() {
      console.log('This is an additional method.');
    }
  };
})();

ExtendedModule.publicMethod(); // Outputs: I am private
ExtendedModule.additionalMethod(); // Outputs: This is an additional method.
Ads