1

我正在阅读 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 + ' ) ';
    }

  };

})();
4

3 回答 3

2

这个例子有点半生不熟。

目标是能够提供公共接口。在该 IIFE 内部,您将界面所需的所有部分放在一起。

您不必通过 return 语句将其传回。

例如,jQuery 就是以同样的方式构建的。而不是返回语句:

var jQuery = (function () { return magic; }());

他们在函数中手动设置window's jQuery(and ) 属性,如下所示:$

(function () { window["jQuery"] = magic; }());

此外,实际发生的事情仍然有点不同。他们将window对象传递给 IIFE 的window参数。那就不必了window。理论上,它可以是您正在扩展的任何先前定义的对象。

var myApp = {};
(function (window, document) { window["jQuery"] = public_interface; }(myApp, document));
myApp.jQuery("...");

在构建类似于 jQuery 的库时,您可以这样做。如果您通常为任何大型库/应用程序命名(一个好主意),您可以在内部缩短名称,以使生活更轻松。

代替:

var NAMESPACED_AWESOME_APP_OF_DOOM = {}; NAMESPACED_AWESOME_APP_OF_DOOM.module1 = {};

您可以执行以下操作:

(function (namespace) {

    var ns = {};
    window[namespace] = ns;

    ns.module1 = {};
    ns.module2 = {};
    ns.service1 = function () {};

}("NAMESPACED_AWESOME_APP_OF_DOOM"));

然后您可以在内部进行所有内部设置,一旦设置完成,您可以在全局范围内按名称引用应用程序。

在其他情况下,您可以为代码创建沙箱,以这种方式使用闭包,使用中介在组件之间来回发送消息。Nicholas Zakas 对此进行了几次很好的讨论。

最后,有时您只想完成一些工作,这与您的程序的其余部分 100% 无关,但仍然需要完成,都是一样的(例如进行兼容性检查并将结果绑定到 DOM 元素, a la Modernizr ... ...或设置只需要存在的cookie,或触发对分析软件的调用... ...等等)。

于 2012-09-16T02:37:08.550 回答
0

在这个特定实例中,匿名函数仅用于防止 CarManager 被其他地方访问,即进入全局范围。

也特定于这个代码实例,它完全没有意义。CarManager 不能被任何其他代码使用。

查看您在评论中提供的链接,http://addyosmani.com/resources/essentialjsdesignpatterns/book/#commandpatternjavascript

据我所知,除了 CarManager.execute 位之外,记录的整个代码部分都将完全无法工作。尝试在匿名函数之外定义 CarManager.execute = ... 将失败,因为 CarManager 不存在。

于 2012-09-16T02:13:28.203 回答
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 )

于 2012-09-16T02:56:07.760 回答