我正在阅读javascript设计模式书,并在阅读“命令模式”时遇到了下面的代码。我一直试图理解为什么这个代码包含一个立即调用的匿名函数,特别是因为没有其他私有变量可以关闭。这与将CarManager声明为对象文字有何不同?
(function(){
var CarManager = {
// request information
requestInfo: function( model, id ){
return 'The information for ' + model + ' with ID ' + id + ' is foobar';
},
// purchase the car
buyVehicle: function( model, id ){
return 'You have successfully purchased Item ' + id + ', a ' + model;
},
// arrange a viewing
arrangeViewing: function( model, id ){
return 'You have successfully booked a viewing of ' + model + ' ( ' + id + ' ) ';
}
};
})();
答案 0 :(得分:2)
这个例子略显不完整。
目标是能够提供公共界面。 在IIFE内部,您可以将界面所需的所有部分组合在一起。
您不必通过return语句将其传回。
例如,jQuery以相同的方式构建。 而不是返回声明:var jQuery = (function () { return magic; }());
他们在函数中手动设置window
的{{1}}(和jQuery
)属性,如下所示:
$
此外,实际发生的事情仍然有点不同。
他们将(function () { window["jQuery"] = magic; }());
对象传递给IIFE的window
参数。
那么它不一定是window
。
理论上,它可以是您正在扩展的任何先前定义的对象。
window
在构建类似于jQuery的库时,您可以执行类似的操作。 如果您通常命名任何大型库/应用程序(一个好主意),您可以在内部缩短名称,以使生活更轻松。
而不是:
var NAMESPACED_AWESOME_APP_OF_DOOM = {}; NAMESPACED_AWESOME_APP_OF_DOOM.module1 = {};
您可以执行以下操作:
var myApp = {};
(function (window, document) { window["jQuery"] = public_interface; }(myApp, document));
myApp.jQuery("...");
然后您可以在内部完成所有内部设置,一旦设置完成,您就可以在全局范围内按名称引用应用程序。
在其他情况下,您可以使用这种方式使用闭包为代码创建沙箱,并使用调解器在组件之间来回发送消息。 尼古拉斯·扎卡斯(Nicholas Zakas)对此进行了几次很好的讨论。
最后,有时你只是想完成一些工作,这与你的程序的其余部分100%无关,但仍然需要完成,所有相同(比如进行兼容性检查并将结果绑定到DOM元素,现代化......或者设置只需要存在的cookie,或者启动对分析软件的调用......等等。
答案 1 :(得分:0)
在此特定实例中,匿名函数仅用于防止CarManager在其他地方访问,即进入全局范围。
此特定于此代码实例,它完全没有意义。任何其他代码都无法使用CarManager。
查看评论中提供的链接http://addyosmani.com/resources/essentialjsdesignpatterns/book/#commandpatternjavascript
据我所知,除了CarManager.execute位之外,记录的整个代码部分将完全无法工作。尝试在匿名函数之外定义CarManager.execute = ...将失败,因为CarManager不存在。
答案 2 :(得分:0)
我是OP。基于上面的讨论,在试图解释作者想要表达的内容之后,我得出结论,以下代码可能是作者想要表达的内容。至少对我来说这似乎是有道理的。
(function(){
var CarManager = {
requestInfo: function(model, id){
/* blah blah */
},
buyVehicle: function(model, id){
/* blah blah */
},
arrangeViewing: function( model, id ){
/* blah blah */
}
};
CarManager.execute = function(name){
return CarManager[name] && CarManager[name].apply(CarManager, Array.prototype.slice(arguments, 1));
}
return CarManager;
}());
基本上,我添加了匿名函数执行返回CarManager对象文字的部分。另外,我在返回之前放置了execute方法(虽然我不太明白为什么它应该在原始CarManager对象之外,除了潜在的代码可读性之外)你怎么看?
(顺便说一下,本书部分的网页版本在这里:http://addyosmani.com/resources/essentialjsdesignpatterns/book/#commandpatternjavascript)