我理解模块模式的原理但是当我看到不同的定义时,我很难理解匿名函数的工作原理。特别是,采取这三个例子
示例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以不同的方式定义:
问题:在我看来,我会做的是示例3,我不明白为什么示例1和2没有按以下方式使用
答案 0 :(得分:2)
您似乎需要了解return
在函数中的工作原理,以便了解所提供示例的行为方式。
示例1 :您创建了一个新变量pub
,并为其添加了两种方法:add
和sub
。最后,您将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个成员函数,即创建命名空间