最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

What's the difference between these two JavaScript patterns - Stack Overflow

programmeradmin9浏览0评论

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 {
        mon: {
            init: function() {
                console.log("mon.init");
            }
        },
        users: {
            init: function () {
                console.log("users.init");
            },
            show: function () {
                 console.log("users.show");
            }
        }
    }
})();

PATTERN #2 (singleton)

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

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

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

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 {
        mon: {
            init: function() {
                console.log("mon.init");
            }
        },
        users: {
            init: function () {
                console.log("users.init");
            },
            show: function () {
                 console.log("users.show");
            }
        }
    }
})();

PATTERN #2 (singleton)

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

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

    show: function() {
      console.log("users.show");
    }
  }
};
Share Improve this question asked Oct 2, 2011 at 4:54 howtodothishowtodothis 1,3054 gold badges18 silver badges31 bronze badges 1
  • The first thing that es to mind is that Pattern 1 allows for initialization code that may include variable or function declarations that immediately go out of scope, thus not contaminating the enclosing scope. – Pablo Commented Oct 2, 2011 at 5:08
Add a ment  | 

3 Answers 3

Reset to default 8

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

var Module = (function(Module) {
  // A ment
  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.

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 {
        mon: {
            init: function() {
                console.log("mon.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.

Your code as written is pretty much the same. However, the first form is much easier to work with as you evolve your code, because it allows you to add private variables and functions. The second form doesn't support this, and you nearly always end up wanting the first form eventually.

发布评论

评论列表(0)

  1. 暂无评论