Javascript - Module Pattern

About

This article shows classic design pattern with ECMAScript on how to organize javascript code with a structure that make possible to:

This structure is known globally as a module in javascript.

The early JavaScript implementation (such as ECMA-262 1)) add no means to organize code such as ESM module, this pattern were then found by developers to organize their code.

Patterns

Module pattern based on IIFE / Anonymous Closure

The Immediately invoked function expression (IIFE) is a common pattern that :

  • permits to not pollute the global variable (all body vars and functions are in the function scope and not in the global)
  • permits to access to all globals
  • permits to pass global variable
  • permit to export by returning

IIFE are also known as Anonymous Closure.

This pattern are also known as the module pattern

Import with argument

You can import via the argument.

For instance, if you want to have access to the global variable JQuery

(function ($) {
  // now have access to globals jQuery (as $) 
}(jQuery));

Export with Return

Example:

let module = (function () {
	let exp = {}; // the public object that will be returned
        let privateVariable = 1; // this variable stays in the function scope and is then private

	// this function stays in the function scope and is then private
	function privateMethod() {
		// ...
	}

	exp.publicProperty = "public property !"; // the attached property is also public
	exp.publicMethod = function () {
		console.log("public method");
	};
	return exp;
}());
  • We can then use it
module.publicMethod();
console.log(module.publicProperty);

Augmentation / Overwrite

var GLOBAL_MODULE = (function (module) {

    // Augmentation
    module.newFunction= function(){
        console.log("new function !")
    }

    // Overwrite 
    let oldOverwrittedMethod= module.overwrittedMethod;
    module.overwrittedMethod = function(){
           console.log("overitted method with access to the old method");
    }

    return module;
}(GLOBAL_MODULE || {}));
  • Usage
GLOBAL_MODULE.newFunction();

The definition of the GLOBAL_MODULE with var is important because it allows to pass it as argument even if it was not defined. If you use let or const, you would get the following error: Cannot access 'GLOBAL_MODULE' before initialization

SubModule

The returned object of the IIFE becomes a property of the module.

MODULE.sub = (function () {
	var my = {};
	// ...

	return my;
}());

Object literal pattern based on function and class

Normal function with closure

A normal function can also be used.

This design pattern makes possible to implement a class (object) with the help of the closure capability of the Javascript function.

The function will behaves like a class but in a function structure.

The call to a module function will instantiate a new function with a new scope.

function User(name){

    // Private
    var username = name;
    
    // Private
    function returnName() { 
        return username;
    } 
    
    // Public
    var publicAPI = { 
        getName: returnName
    }; 
    
    return publicAPI; 

} 

// User() creates an instance of the User module
var foo = User("foo"); 
var bar = User("bar"); 
console.log( foo.getName()+" loves "+bar.getName() );

The new keyword was not used (ie new User()) because User is not a class to be instantiated, User() is just a function.

Class

class are by default good candidate for module creation.


Powered by ComboStrap