9个回答

50

立即调用函数表达式(IIFE)

IIFE是局部范围化全局变量/属性并保护JavaScript代码库免受外部干扰(例如第三方库)的理想解决方案。如果您正在编写将在许多不同环境中运行的jQuery代码(例如jQuery插件),那么使用IIFE来局部范围化jQuery非常重要,因为您不能假定每个人都在使用$来别名jQuery。以下是操作方式:

   // IIFE - Immediately Invoked Function Expression
  (function($, window, document) {
      // The $ is now locally scoped

      // The rest of your code goes here!

  }(window.jQuery, window, document));
  // The global jQuery object is passed as a parameter

如果你不喜欢滚动到源文件底部查看你传递给IIFE的全局变量/属性,你可以这样做:

   // IIFE - Immediately Invoked Function Expression
  (function(yourcode) {

      // The global jQuery object is passed as a parameter
      yourcode(window.jQuery, window, document);

      }(function($, window, document) {

          // The rest of your code goes here!

      }
  ));

如果您想了解更多有关IIFE的信息,请阅读我的博客文章,标题为"我爱我的IIFE"

jQuery Ready事件

许多开发人员将他们的所有代码都包裹在jQuery的ready事件中,如下所示:

   $("document").ready(function() {
      // The DOM is ready!
      // The rest of your code goes here!
  });

或者像这样更简短的版本:

   $(function() {
      // The DOM is ready!
      // The rest of your code goes here!
  });
如果您正在执行以上任何一种模式,则应考虑将不依赖于DOM的应用程序部分(例如方法)移动到ready事件处理程序之外。像这样:

如果您正在执行以上任何一种模式,则应考虑将不依赖于DOM的应用程序部分(例如方法)移动到ready事件处理程序之外。像这样:

   // IIFE - Immediately Invoked Function Expression
  (function(yourcode) {

      // The global jQuery object is passed as a parameter
      yourcode(window.jQuery, window, document);

      }(function($, window, document) {

          // The $ is now locally scoped 
          $(function() {

              // The DOM is ready!

          });

          // The rest of your code goes here!

      }
  ));

这种模式使得从代码设计的角度来看,更容易将逻辑分离出来,因为不需要将所有内容都封装在单个事件处理程序回调函数中。它还可以提高应用程序的页面加载性能,因为不需要立即初始化所有内容。一个很好的例子是惰性绑定DOM事件处理程序,它们不需要在DOM准备就绪时绑定。

改编自我的jQuery最佳实践博客文章:http://gregfranko.com/blog/jquery-best-practices/


谢谢您的解释。请考虑在那个演示文稿上启用某种评论系统 :) - Red
希望大家能在我的博客文章下留言评论 =) - Greg Franko
1
@Greg Franko:只是想说,喜欢那个演示文稿:它简洁而有效。最近几周一直在参考它,感觉我的jQuery编程已经因此大大提高了。干杯!希望能看到更多这样的系列。 - HorseloverFat
我在 Stack Overflow 和网络上搜索,发现所有的答案都是关于应用程序或 jQuery 插件等方面的好处。但是对于一个普通的网页,使用什么有什么区别吗?很抱歉打扰这个帖子,但这个答案是唯一一个解释差异的好答案。 - dingo_d
代码 $("document").ready(function() { 应该替换为 $(document).ready(function() { - Farahmand

16
你的代码和“建议”的方法唯一的区别在于兼容性和可能更好的压缩。速度没有差异。
window.jQuery作为你的IIFE(立即调用的函数表达式)的第一个参数传递,并在IIFE中将其命名为$,只是让你能够使用jQuery,而不会干扰其他将自己分配给全局$的库。如果你不使用任何其他将自己分配给全局$的库,那么你的IIFE的第一个参数将不会起到任何作用。
windowdocument传递给你的IIFE将允许JS最小化器将你的代码转换为如下所示的内容(无空格),这样可以获得略微更好的压缩效果:
(function(a, b, c) {
    a(c).ready(function() {
        // ...
    });
})(window.jQuery, window, document);

如果您不经常使用 windowdocument,建议使用以下方式:
;(function($) {
    $(function() {
        ...
    });
})(jQuery);

1
@dwerner:迫不及待地想要兑换奖品 ;) - Blender
这更多地涉及到内存管理而非速度问题。你会看到很多开发者把所有的代码都扔进 DOM 准备函数中。这意味着通常情况下,所有的事件处理器、插件等都会在 DOM 就绪后被绑定和调用(而不是应用程序实际需要它们时)。希望“其余的代码放这里”注释能够影响开发者将他们的应用逻辑放在 DOM 准备函数之外,然后只包含所需内容。 - Greg Franko
在这个问题中,两个代码片段之间绝对没有区别,Greg Franko的解释很好,但第二个片段并没有帮助到关注点分离,事实上,它更难以阅读和理解。无论如何,将代码从DOM就绪块中移出足够容易。这应该是被接受的答案,因为缩小文件大小是第二种方法的唯一好处,但这可能只是微观优化。话虽如此,我通常会包装在IIFE中,但原因不同。 - Matt Styles

5
  1. $(function(){}) 相当于 $('document').ready(function(){});。你可以选择哪种方法使用,但后者是两者中较老的一种,并且更加冗长。

  2. 第二种方法是明确尝试防止全局变量,并注入已知的全局变量$windowdocument。这建议是为了增加我们对如何轻松引入全局变量的认识,并尽可能地将我们注入页面的代码“清空”。此外,请注意,如果您遵循所示的注释,则第二种方法不等同于第一种。因为$被插入为参数,所以这段代码与其他可能希望拥有$符号的库兼容。

特别是,//余下的代码在此处 处于可能在文档准备好之前或在该事件被触发时执行的位置。将其放置在传递给 $ 的函数内部。


我理解“代码的其余部分”,但为什么他们推荐方法2呢? - Red
1
可以放心地使用其他库,如Mootools,或任何想要将$用作全局变量的库,它不会出现问题。如果$的值更改了,其他方法可能会出现问题。 - dwerner
@dweerner 这很有道理。但是作者更喜欢方法2,因为它在页面加载性能方面更好。 - Red
1
第二种方法没有任何使其更高效的原因。使代码更易于阅读、理解和更少脆弱是有价值的,然而性能并不是一切。 - dwerner

3

你的链接已经给出了答案:

如果您知道代码运行的环境,以下内容是可以的。

如果您不在意页面加载性能,以下内容是可以的。

如果您不关心最佳实践,以下内容是可以的。

 $("document").ready(function() {
    // The DOM is ready!
    // The rest of the code goes here
  });

但是他们建议,如果您不知道代码运行的环境,最好使用以下方式:

更好的页面加载性能

// IIFE - Immediately Invoked Function Expression
  (function($, window, document) {

    // The $ is now locally scoped 

   // Listen for the jQuery ready event on the document
   $(function() {

     // The DOM is ready!

   });

   // The rest of the code goes here!

  }(window.jQuery, window, document));
  // The global jQuery object is passed as a parameter

我可以看出来,问题是为什么他们推荐方法2? - Red
2
那么这怎么回答问题呢?你只是抄写了幻灯片。 - Blender
2
是的,第二种方法适用于我们不知道代码将在哪个环境下运行以及更好的页面加载性能。http://gregfranko.com/blog/i-love-my-iife/ - Balaji Kandasamy

3

如果您将$用作jQuery的别名,则

   $(document).ready(function(){})

相同
  (function($, window, document) {

  // The $ is now locally scoped 

 // Listen for the jQuery ready event on the document
  $(function() {

    // The DOM is ready!

  });

  // The rest of the code goes here!

 }(window.jQuery, window, document));

正如早前的回答中所指出的那样,第二种方法将jQuery对象传递给立即调用的函数表达式,使得你不必自由地使用$别名来使用jQuery,这基本上将变量和代码保持私有,不会污染全局命名空间。

简而言之,如果你采用第一种方法并使用其他使用$的库,你将会遇到冲突。


1
在罕见情况下,如果您需要使用旧版本的jQuery(如果我没记错的话-1.8.X之前),每当您指定两个document.ready块时,在IE9中只会触发第一个块。
现在这是我曾经遇到过一两次的罕见错误,但我认为值得注意。

0

你可以使用jQuery的文档就绪事件,在文档完全加载时触发该事件。

 $(function () {
    setTimeout(function () {
        // your code
    }, 0);
})

0

基于 JQuery 文档:

All three of the following syntaxes are equivalent:

$(document).ready(handler)
$().ready(handler) (this is not recommended)
$(handler)

http://api.jquery.com/ready/


请确认一下:您是说这两种方法会做相同的事情吗? - Red
是的,它们是相同的,在DOM准备就绪时执行代码。 - rderoldan1

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接