【问题标题】:Why define an anonymous function and pass it jQuery as the argument?为什么要定义一个匿名函数并将 jQuery 作为参数传递给它?
【发布时间】:2012-04-29 10:50:27
【问题描述】:

我正在查看来自主干.js 截屏视频的优秀 peepcode 演示代码。在其中,主干代码都包含在一个匿名函数中,该函数被传递给 jQuery 对象:

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

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

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

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

【问题讨论】:

标签: javascript jquery backbone.js


【解决方案1】:

您展示的两个代码块在执行时间和执行原因方面存在巨大差异。它们并不相互排斥。它们的用途不同。

JavaScript 模块


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

这是一种“JavaScript 模块”模式,通过立即调用函数实现。

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

this 的实现是一个由调用(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 模块模式中执行此操作,以便我可以为我的代码提供封装和隐私。我倾向于使用“Revealing Module”模式(参见上面的第一个链接)来提供对我在模块之外需要的位的访问。

通过在 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();
});

【讨论】:

  • 感谢您的详细回复。我知道只有在 DOM 就绪事件触发时才会调用 DOMReady 函数,但从未真正想到这会是一个问题。将代码拆分为在模块中定义主干位,然后在准备好的 dom 中与它们进行交互确实似乎是最好的方法
  • 有趣的是,带有主干 src 的“todo”示例应用程序将 dom 中的所有内容都准备好了。
  • 别忘了 javascript 模块模式也称为 IIFE
  • 匿名函数本质上是在 DOM 就绪的同时执行的,那么它如何使它们更高效??
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      更多详情请参考http://docs.jquery.com/Plugins/Authoring#Getting_Started

      【讨论】:

        【解决方案5】:

        两者都用。

        你传入 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 */ });
        猜你喜欢
        • 2021-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-14
        • 2019-11-23
        • 2011-05-11
        • 1970-01-01
        相关资源
        最近更新 更多