Module Pattern in JavaScript

Need for writing modular JavaScript code increases with the size of your code base. Namespaces would help you up to a certain extent. However, it has some limitations. As codebase grows, namespaces tend to go deeper, and it doesn’t help with managing dependencies. Module pattern leverages closure and function scope to create encapsulation to prevent unnecessary details leaking into global scope.

Let’s create a module

All variables and functions are wrapped in an immediately invoked function expression(IIFE) and only an object containing the members to be exposed as public is returned. Following is the example of creating a module named automobile

var automobile = (function () {
    var currentOilLife = 80, //Just hard coded value
        serviceOilLife = 20; //service required if oil life is below 20%

    var Car = (function () {
        function Car(make, model) {
            this.make = make;
            this.model = model;
        }

        Car.prototype.isServiceRequired = function () {
            return currentOilLife < serviceOilLife;
        };

        return Car;
    }());

    return{
        Car: Car
    };

}());

The function returns an object exposing Car class and isValidVIN function, all other variables and functions(i.e. currentOilLife and serviceOilLife) remains private to this module. Need for explicitly returning the members to be exposed forces to think in terms of interface to be exposed to the collaborator or users of the module. It provides a nice structure suitable for creating loosely coupled components for your application and sharing reusable code across other applications.

Breaking the module

The structure we used to create the module would require all the code of a module to be in one function scope and thus in a single file. That wouldn’t scale well, lets updated the module so that it could be spread across multiple files.

Following is the updated version to pass the module definition to the immediately invoked function if it exists or an empty object. Public members of the module are attached to the module definition passed as an argument instead of creating a brand new object. automobile || {} simply means - pass the variable name automobile if it is defined, else pass the new object {}.

var automobile = (function (automobile) {
    var currentOilLife = 80, //Just hard coded value
        serviceOilLife = 20, //service required if oil life is below 20%
        isValidVIN;

    isValidVIN = function (vin) {
        return vin !== null && vin.length === 17;
    };

    var Car = (function () {
        function Car(make, model) {
            this.make = make;
            this.model = model;
        }

        Car.prototype.isServiceRequired = function () {
            return currentOilLife < serviceOilLife;
        };

        return Car;
    }());


    automobile.Car = Car;
    automobile.isValidVIN = isValidVIN;
    return automobile;
}(automobile || {}));

Using this structure, you could break a module across multiple files. Now, you could declare used car related functions of the automobile module in a separate file as shown below.

var automobile = (function (automobile) {
    var findUsedCars = function (year, milage, maxprice) {
        return [{ make: 'Honda', model: 'Accord', year: 2008, price: 12000},
                { make: 'Toyota', model: 'Venza', year: 2009, price: 19500},
                { make: 'Ford', model: 'Escape', year: 2012, price: 20000}];
    };

    automobile.findUsedCars = findUsedCars;
    return automobile;
}(automobile || {}));

Passing the dependencies

Let’s create a new module called dealer which requires automobile module. Extending the pattern used in the previous example, pass automobile as a second argument, which is referenced as auto. Of course, you could have directly used the automobile module in dealer module, however explicitly passing the dependencies as arguments gives a great degree of flexibility. You could easily swap the modules as long as it provides the same interface.

var dealer = (function (dealer, auto) {
    var deliverCar = function (make, model) {
        return new auto.Car(make, model);
    };

    dealer.deliverCar = deliverCar;
    return dealer;
} (dealer || {}, automobile));

Here, the assumption is that the automobile module is already loaded and available when dealer module is being created. This works fine when the amount of code and number of modules are small. Once your application becomes large and complex, loading all the module upfront would incur unnecessary overhead. It would be ideal if we could load the modules from the server as and when require. Let’s say we have three modules corresponding to three major areas of the application - automobile, dealer and service. We will assume that the service is a standalone module without dependency on other two modules. When a user is on the service part of the application, automobile and dealer module need not be loaded. If user goes to dealer part of the application, the dealer module should be loaded along with automobile module as that is a dependency. Asynchronous Module Definition or AMD provides API for achieving the same goal, where dependencies could be declared explicitly and loaded asynchronously. ECMAScript6 plan includes proposal called Harmony modules, which would bring native module system to JavaScript.