为什么模块模式?

时间:2011-09-19 13:00:07

标签: javascript design-patterns

我已经阅读了很多关于模块模式的内容。 好吧它带来结构,私人方法等...... 但是使用下面的代码,我可以在不使用它的情况下获得相同的行为。

function Human()
{
  // private properties
  var _name='';
  var _age=0;


  // private methods
  function created()
  {
    console.log("Human "+_name+" called");
  };

  // public
  this.setName = function(name){
    _name=name;
    created(); 
  };

}


var h1 = new Human();

h1.setName("John");

那么,最终模块模式的真正优势是什么?

3 个答案:

答案 0 :(得分:11)

我认为这个例子可以帮助您澄清模块模式的用处。

模块模式

  

模块模式被广泛使用,因为它提供了结构并有助于组织   随着代码的增长你的代码。与其他语言不同,JavaScript没有特殊的语法   对于包,但模块模式提供了创建自包含解耦的工具   代码段,可以被视为黑盒功能并添加,   根据软件的(不断变化的)要求替换或删除   你正在写作。

模块模式是几种模式的组合,即:

  • 命名空间
  • 即时功能
  • 私人和特权会员
  • 声明依赖关系

第一步是设置命名空间。我们使用之前的 namespace()函数 在本章中,启动一个提供有用数组方法的示例实用程序模块:

MYAPP.namespace('MYAPP.utilities.array');

下一步是定义模块。该模式使用即时函数 如果需要隐私,则提供私人范围。 immediate函数返回一个对象 - 具有公共接口的实际模块,可供消费者使用 模块:

 MYAPP.utilities.array = (function () {
    return {
    // todo...
    };
 }());

接下来,让我们为公共接口添加一些方法:

MYAPP.utilities.array = (function () {
   return {
      inArray: function (needle, haystack) {
         // ...
      },
      isArray: function (a) {
         // ...
      }
   };
}());

使用immediate函数提供的私有作用域,可以声明一些 私有财产和方法。就在立即功能的顶部 也将是声明模块可能具有的任何依赖项的地方。以下 在变量声明中,您可以选择放置任何一次性初始化代码 有助于设置模块。最终结果是立即函数返回的对象 包含模块的公共API:

MYAPP.namespace('MYAPP.utilities.array');
MYAPP.utilities.array = (function () {
   // dependencies
   var uobj = MYAPP.utilities.object,
       ulang = MYAPP.utilities.lang,
       // private properties
       array_string = "[object Array]",
       ops = Object.prototype.toString;
       // private methods
       // ...
       // end var
   // optionally one-time init procedures
   // ...
   // public API
   return {
      inArray: function (needle, haystack) {
         for (var i = 0, max = haystack.length; i < max; i += 1) {
            if (haystack[i] === needle) {
               return true;
            }
         }
      },
      isArray: function (a) {
         return ops.call(a) === array_string;
      }
      // ... more methods and properties
   };
}());

模块模式是一种广泛使用且强烈推荐的组织您的方式 代码,尤其是随着代码的增长。

“JavaScript模式,由Stoyan Stefanov撰写 (O'Reilly出版)。版权所有2010 Yahoo!,Inc.,9780596806750

答案 1 :(得分:8)

不确定为什么没人能正确回答这个问题。我可以看到在某种模式中使用自动调用函数的潜力,这些模式旨在使私有变量可以继承,但你绝对正确。

使用模块模式代替核心语言函数构造函数没有任何好处。它是完全相同的语言机制(闭包),允许持久内部变量作为不可访问的实体存在,只有更多的代码。

在JS中,函数构造函数遵循与触发函数相同的范围规则。范围和结束是在定义点设定的。函数构造函数的内部var所依赖的原因是因为具有在引用该var的同一构造函数内定义的方法的实例仍然存在。

唯一改变的是你已经在构造函数中消除了原型方法的使用,并且必须为继承的方法设置自己的继承机制。

答案 2 :(得分:0)

目前有大量的JavaScript项目正在使用模块模式构建,也许您有自己的想法,并希望确保代码易于阅读且结构良好。 通过学习几种模式,可以使您的应用程序更易于构建和维护。 这些模式由最有JavaScript才能的开发人员使用,例如,人们构建节点js,JQuery,bootstrap,angular等。 简单示例:

  function foo (){
    console.log("foobar");
};

foo();

当我们调用此简单方法时,我们会注意到它可以在全局名称空间中访问,而当我们谈论大型应用程序时,这是一个巨大的问题。

有时我们称其为混乱的全局名称空间。 这是一个问题,原因是浏览器中发生了太多事情,您可能会在浏览器中加载angular,bootstrap和Jquery,甚至可能还有其他一些JavaScript库。 现在,如果您必须浏览一堆使全局名称空间混乱的变量,那么就可以退出。实际上,如果您创建的变量与另一个库中的变量具有相同的名称,这甚至可能是灾难性的。 最基本的模块模式将解决此问题。为此,我在一个自执行的匿名函数中描述了我的代码,现在看起来像这样: 从此:

function foo (){
    console.log("foobar");
};

foo();

对此:

(function(){function foo (){
    console.log("foobar");
};

foo();
}());

我们包装了一个函数封装(),然后我可以调用它,需要封装函数封装的原因是因为没有名称的函数本身将返回未定义的值,但是当我们封装函数括号时,我们实质上是在说待整个事情都是一个表达式,可以立即求值,而不必进行命名或赋值,现在,当我们运行代码并检查浏览器时,我们将看到现在全局名称空间不再混乱我的变量了。我们可以看到foo是未定义的。

关于JavaScript基本模块模式的源码树屋研讨会
相关问题