具有匿名功能的Javascript模块模式

时间:2014-03-29 17:15:07

标签: javascript anonymous-function

我理解模块模式的原理但是当我看到不同的定义时,我很难理解匿名函数的工作原理。特别是,采取这三个例子

示例1,(来自http://viralpatel.net/blogs/javascript-module-pattern/

CalcModule = (function(){
                var pub = {};
                pub.add = function(a, b) {
                             console.log('in add()', a, b);
                             return a + b;
                };
                pub.sub = function(a, b) {
                             console.log('in sub()', a, b);
                             return a - b;
                };
                return pub;
})();

用作

CalcModule.add(5,2) //returns : 7

示例2(来自Learning JavaScript Design Patterns 1.5.2,Addy Osmani)

var testModule = (function () {

  var counter = 0;

  return {

    incrementCounter: function () {
      return counter++;
    },

    resetCounter: function () {
      console.log( "counter value prior to reset: " + counter );
      counter = 0;
    }
  };
})();

用作

testModule.incrementCounter()

示例3(来自http://css-tricks.com/how-do-you-structure-javascript-the-module-pattern-edition/

var s,
NewsWidget = {

  settings: {
    numArticles: 5,
    articleList: $("#article-list"),
    moreButton: $("#more-button")
  },

  init: function() {
    // kick things off
    s = this.settings;
  }
};
顺便说一句,我不知道如何使用它。

如您所见,方法,例如add,incrementCounter和init以不同的方式定义:

  • 示例1:通过私有变量pub
  • 示例2:在返回方法中!
  • 示例3:作为构造函数NewsWidget的方法

问题:在我看来,我会做的是示例3,我不明白为什么示例1和2没有按以下方式使用

  • 示例1:CalcModule.pub.add(5,2)
  • 示例2:不知道

3 个答案:

答案 0 :(得分:2)

您似乎需要了解return在函数中的工作原理,以便了解所提供示例的行为方式。

示例1 :您创建了一个新变量pub,并为其添加了两种方法:addsub。最后,您将pub变量返回到CalcModule

因此,当您调用CalcModule时,它会使用两种方法返回以下对象:

CalcModule = {
   add: function() {...},
   sub: function() {...}
}

示例2:让我们重写示例2,类似于示例1 ...

var testModule = (function () {

  var counter = 0;
  var pub;

  pub.incrementCounter: function () {
      return counter++;
  }

  pub.resetCounter: function () {
      console.log( "counter value prior to reset: " + counter );
      counter = 0;
  }

  return pub;
})();

我们知道pub是一个对象......

pub = {
   incrementCounter: function() { ... },
   resetCounter: function() { ... }
}

我们将pub返回testModule ...因此......

testModule = {
   incrementCounter: function() {...},
   resetCounter: function() {...}
}

希望这有用。

答案 1 :(得分:0)

在示例1中,pub通过return语句和返回值的赋值分配给变量CalcModule,因此CalcModule直接成为pub的别名。这就是它CalcModule.add()的原因。从IIFE return pub;返回的值将分配给CalcModule。它好像是CalcModule = pub

在示例二中,testModule通过返回值分配了一个未命名的对象,该对象具有方法incrementCounter()resetCounter()。因此,testModule再次成为该对象的命名别名,因此您可以将该对象中的方法称为testModule.incrementCounter()testModule.resetCounter()

如图所示的示例1没有示例3的优势,因此如果您对示例3更熟悉,那就没问题了。您的示例3有一个变量s,它似乎有点奇怪且不符合字符,因为您在调用NewsWidget.init()时设置了一个全局变量,这通常不是一个好的设计模式。也许您想从.init()返回该值。

示例2使用IIFE(立即调用的函数表达式)创建一个安全且私有的位置来存储不在全局命名空间中的counter变量,不能与任何其他代码冲突且无法访问其他代码示例您自己的方法。这实际上是一种创建私人"只有您的方法可以访问的变量。示例1也可以使用该功能,但是示例3没有使用该功能的选项,因为它没有封闭的IIFE。

答案 2 :(得分:0)

重要的是要理解函数是JavaScript中的一等公民。这意味着函数可以像任何其他对象一样传递并分配给变量,模块也是如此。

在您的第一个示例中,将2个函数( pub.add,pub.sub )创建为模块 pub 的成员,然后分配给变量 CalcModule

在第二个示例中,返回变量返回一个对象文字,它有两个键/值对,键是函数名,值是函数。指定该对象文字等效于将变量指定为2个成员函数,即创建命名空间