为什么定义一个匿名函数并将jQuery作为参数传递给它?


96

我正在看ribs.js截屏视频中出色的peepcode演示代码。在其中,主干代码全部封装在传递给jQuery对象的匿名函数中:

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

在我自己的主干代码中,我将所有代码包装在jQuery DOM'ready'事件中:

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

第一种方法的目的/优势是什么?这样做会创建一个匿名函数,然后将其作为传递给函数参数的jQuery对象立即执行,从而有效地确保$是jQuery对象。这是唯一的观点-保证jQuery绑定到“ $”还是有其他原因呢?


4
您应该先浏览SO。
亚历山大

与其他库的互操作性-如果页面作者需要使用$.noConflict(),则第一个示例仍然有效。
DCoder 2012年

可能重复的内容:jQuery和$问题
2012年


@Alexander,但随后其他人将首先在SO上找到此问题。:-)
caiosm1005

Answers:


179

您显示的两个代码块在执行时间和执行原因上有很大不同。它们不是彼此排斥的。它们的目的不同。

JavaScript模块


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

这是一个“ JavaScript模块”模式,通过立即调用功能实现。

该代码的目的是为您的代码提供“模块化”,保密性和封装性。

此功能的实现由调用(jQuery)括号立即调用。将jQuery传递到括号中的目的是为全局变量提供局部范围。这有助于减少查找$变量的开销,并在某些情况下允许优化器进行更好的压缩/优化。

立即调用功能会立即执行。功能定义一完成,功能即被执行。

jQuery的“ DOMReady”功能

这是jQuery的“ DOMReady”函数的别名:http : //api.jquery.com/ready/


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

当DOM准备由您的JavaScript代码操纵时,将执行jQuery的“ DOMReady”函数。

骨干模块中的模块与DOMReady

在jQuery的DOMReady函数中定义Backbone代码是一种不好的形式,并有可能损害您的应用程序性能。在DOM加载并准备好操作之前,不会调用此函数。这意味着您要等到浏览器至少解析一次DOM之后再定义对象。

最好在DOMReady函数之外定义Backbone对象。除其他外,我更喜欢在JavaScript模块模式内执行此操作,以便为代码提供封装和隐私。我倾向于使用“显示模块”模式(请参见上面的第一个链接)来提供对模块外部所需位的访问。

通过在DOMReady函数之外定义对象并提供引用它们的方式,可以使浏览器抢先处理JavaScript,从而有可能加快用户体验。这也使代码更加灵活,因为您可以随意移动事物,而不必担心在移动事物时创建更多的DOMREady函数。

即使您在其他地方定义了Backbone对象,您仍然可能仍将使用DOMReady函数。原因是许多Backbone应用程序需要以某种方式操作DOM。为此,您需要等待DOM准备就绪,因此,在定义应用程序之后,需要使用DOMReady函数来启动应用程序。

您可以在网上找到很多这样的示例,但这是一个非常基本的实现,同时使用Module和DOMReady函数:



// 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();
});

1
感谢您的详细回复。我只在DOM ready事件触发时才知道DOMReady函数,但从未真正想到这会成为问题。将代码拆分为定义模块中的骨干位,然后在准备好dom的过程中与它们进行交互似乎确实是最好的方法
Matt Roberts

2
有趣的是,带有主干src的“ todo”示例应用程序已将dom中的所有内容准备就绪。
马特·罗伯茨

2
别忘了javascript模块模式也称为IIFE
2014年

1
匿名函数本质上是在DOM准备就绪的同时执行的,这如何使它们更有效?
bhavya_w 2014年

14

作为次要说明,将$作为参数传递给匿名函数会使$在该函数中成为本地函数,如果$函数被调用很多,则对性能的影响很小。这是因为javascript首先在本地范围内搜索变量,然后一直向下遍历到窗口范围(通常位于$)。


9

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

没有这种关闭,您应该使用jQuery而不是$整个时间。



2

同时使用。

自我传递函数,您可以在其中传递jQuery来防止库冲突,并确保jQuery与$一样可用。

和.ready()快捷方式方法是仅在DOM已加载后才需要运行JavaScript的方法:

(function($) {
    $(function(){
          //add code here that needs to wait for page to be loaded
    });

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

我在SO的其他地方找到的较短版本(也保护未定义)jQuery(function ($, undefined) { /* Code */ });
Jared Gotte
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.