关于javascript:为什么要定义一个匿名函数并将jquery作为参数传递?

Why define an anonymous function and pass it jQuery as the argument?

我正在查看主干.js屏幕上优秀的peepcode演示代码。其中,主干代码都包含在传递jquery对象的匿名函数中:

1
2
3
(function($) {
  // Backbone code in here
})(jQuery);

在我自己的主干代码中,我刚刚将所有代码包装在jquerydom"ready"事件中:

1
2
3
$(function(){
  // Backbone code in here
});

第一种方法的优点是什么?这样做会创建一个匿名函数,然后立即执行该函数,并将jquery对象作为函数参数传递,从而有效地确保$是jquery对象。这是唯一一个保证jquery绑定到"$"的点,还是有其他原因来这样做?


您所显示的两个代码块在执行时间和执行原因上有很大的不同。它们不是互相排斥的。它们的作用不同。

javascript模块

1
2
3
(function($) {
  // Backbone code in here
})(jQuery);

这是一个"javascript模块"模式,通过一个立即调用的函数实现。

  • http://addyosmani.com/resources/essentialjsdignpatterns/book/modulepatternjavascript
  • 网址:http://www.adequatelygood.com/2010/3/javascript-module-pattern-in-depth

此代码的目的是为代码提供"模块化"、隐私和封装。

此函数的实现是由调用(jQuery)括号立即调用的函数。将jquery传入括号的目的是为全局变量提供局部作用域。这有助于减少查找$变量的开销,并在某些情况下允许更好地压缩/优化迷你服务器。

立即调用函数是立即执行的。函数定义完成后,立即执行函数。

jquery的"domready"函数

这是jquery的"domready"函数的别名:http://api.jquery.com/ready/

1
2
3
$(function(){
  // Backbone code in here
});

jquery的"dom ready"函数在dom准备好被JavaScript代码操纵时执行。

主干代码中的模块与domready

在jquery的domready函数中定义主干代码是不好的形式,并且可能会损害应用程序的性能。在DOM加载并准备好被操作之前,不会调用此函数。这意味着在定义对象之前,您需要等待浏览器至少分析一次DOM。

最好在domready函数之外定义主干对象。我,和其他许多人一样,更喜欢在JavaScript模块模式中这样做,以便为我的代码提供封装和隐私。我倾向于使用"暴露模块"模式(参见上面的第一个链接)来提供对模块外部所需位的访问。

通过在domready函数之外定义对象,并提供一些引用它们的方法,您可以让浏览器在处理您的javascript方面取得先机,从而可能加快用户体验。它还使代码更加灵活,因为您可以在不必担心在移动代码时创建更多domready函数的情况下移动代码。

即使您在其他地方定义了主干对象,也可能会使用domready函数。原因是许多主干应用程序需要以某种方式操作DOM。要做到这一点,您需要等到dom准备就绪,因此您需要在定义应用程序之后使用dom ready函数来启动应用程序。

你可以在网上找到很多这样的例子,但是这里有一个非常基本的实现,使用模块和domready函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Define"MyApp" as a revealing module

MyApp = (function(Backbone, $){

  var View = Backbone.View.extend({
    // do stuff here  
  });

  return {
    init: function(){
      var view = new View();
      $("#some-div").html(view.render().el);
    }
  };

})(Backbone, jQuery);



// Run"MyApp" in DOMReady

$(function(){
  MyApp.init();
});


作为一个次要的旁注,将$as作为参数发送给匿名函数会使$local成为该函数的一部分,如果大量调用$function,则该函数的性能影响较小。这是因为JavaScript首先在本地范围内搜索变量,然后一直向下遍历到窗口范围(通常是$所在的范围)。


它确保即使使用了$.noConflict(),也可以在该闭包内始终使用$

如果没有这个关闭,你应该一直使用jQuery,而不是$


这是为了避免$variable的潜在冲突。如果其他东西定义了一个名为$的变量,则您的插件可能使用了错误的定义。

有关详细信息,请参阅http://docs.jquery.com/plugins/authoring入门


两者兼用。

自我调用函数,在该函数中传递jquery以防止库冲突,并确保jquery可用,正如您对$所期望的那样。

以及.ready()快捷方式方法,仅在加载了dom之后才运行javascript:

1
2
3
4
5
6
7
(function($) {
    $(function(){
          //add code here that needs to wait for page to be loaded
    });

    //and rest of code here
})(jQuery);