Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between these two JavaScript patterns

I am trying to organize my JavaScript better. My goal is to have modular architecture that I can break into separate files (sitename.js, sitename.utils.js etc).

I'd like to know what are advantages and disadvantages of these two patterns and which one is more suitable for breaking into modules that live in separate files.

PATTERN #1 (module pattern)

var MODULE = (function () {

    //private methods

    return {
        common: {
            init: function() {
                console.log("common.init");
            }
        },
        users: {
            init: function () {
                console.log("users.init");
            },
            show: function () {
                 console.log("users.show");
            }
        }
    }
})();

PATTERN #2 (singleton)

var MODULE = {
  common: {
    init: function() {
        console.log("common.init");
    }
  },

  users: {
    init: function() {
      console.log("users.init");
    },

    show: function() {
      console.log("users.show");
    }
  }
};
like image 592
howtodothis Avatar asked Oct 02 '11 04:10

howtodothis


People also ask

What are the different JavaScript patterns?

They are categorized in three groups: Creational, Structural, and Behavioral (see below for a complete list). In this tutorial we provide JavaScript examples for each of the GoF patterns.

How many types of design patterns are there in JavaScript?

The book explores the capabilities and pitfalls of object-oriented programming, and describes 23 useful patterns that you can implement to solve common programming problems. These patterns are not algorithms or specific implementations.

What is a JavaScript pattern?

What is a Pattern? A pattern is a reusable solution that can be applied to commonly occurring problems in software design - in our case - in writing JavaScript web applications. Another way of looking at patterns are as templates for how we solve problems - ones which can be used in quite a few different situations.


2 Answers

Personally, I recommend an extension of #1, as follows:

var Module = (function(Module) {
  // A comment
  Module.variable1 = 3;

  /**
   * init()
   */
  Module.init = function() {
    console.log("init");
  };

  // ...

  return Module;
})(Module || {});

I like this pattern for a couple reasons. One, documentation (specifically javadoc-style) look more natural when all your functions are declarations rather than a big hash. Two, if your submodules grow in size, it lets you break them into multiple files without any refactoring.

For example, if Module.Users were to go into its own file:

var Module = Module || {};
Module.Users = (function(Users) {
  /**
   * init()
   */
  Users.init = function() {
    console.log("Module.Users.init");
  };

  // ...

  return Users;
})(Module.Users || {});

Now "module.js" and "module.users.js" can be separate files, and they'll work regardless of the order they are loaded. Also note the local scoping of the module name - this is very handy if your module name is long, because you can take "MyApp.Users.EditScreen" and refer to it with a variable like "ES" within the scope of your module definition.

like image 154
Elliot Nelson Avatar answered Sep 21 '22 14:09

Elliot Nelson


The first pattern allows for private variables, methods, etc via closures. For example:

var MODULE = (function () {

    var privateStuff = 'This is private';

    var doStuff = function(obj) {
        console.log('Doing stuff...');
        console.log(privateStuff);
    };

    return {
        common: {
            init: function() {
                console.log("common.init");
                doStuff(this);
            }
        },
        users: {
            init: function () {
                console.log("users.init");
            },
            show: function () {
                 console.log("users.show");
            }
        }
    }
})();

privateStuff and doStuff are not properties of the object, and are not available to anything but what's defined inside the function that returns MODULE. So showing an example for how to do this with #2 is not possible.

JS doesn't have the concept of private members, so you can't define them via a regular object literal. So if you need private stuff, go for the first option. If you don't, though, #2 is simpler.

like image 45
cHao Avatar answered Sep 23 '22 14:09

cHao