这个JavaScript / jQuery语法如何工作:( function(window,undefined){})(window)?

时间:2010-04-26 18:58:59

标签: javascript jquery syntax

你有没有看过 jQuery 1.4 源代码,并注意到它是如何以下列方式封装的:

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);

我读过一篇关于JavaScript Namespacing的文章和另一篇名为“An Important Pair of Parens”的文章,所以我知道这里发生了什么。

但我以前从未见过这种特殊的语法。在那里做什么 undefined ?为什么 window 需要通过然后再次出现?

5 个答案:

答案 0 :(得分:157)

undefined是一个普通变量,可以使用undefined = "new value";简单地更改。所以jQuery创建了一个真正未定义的本地“未定义”变量。

出于性能原因,窗口变量是本地的。因为当JavaScript查找变量时,它首先遍历局部变量,直到找到变量名称。如果找不到它,JavaScript将通过下一个范围等,直到它过滤全局变量。因此,如果窗口变量是本地的,JavaScript可以更快地查找它。 更多信息:Speed Up Your JavaScript - Nicholas C. Zakas

答案 1 :(得分:53)

<强>未定义

通过将undefined声明为参数但从未向其传递值确保它始终未定义,因为它只是全局范围中可以覆盖的变量。这使a === undefined成为typeof a == 'undefined'的安全替代品,可以节省一些字符。它还使代码更加简化,因为undefined可以缩短为u,例如,可以节省更多字符。

<强>窗口

window作为参数传递会在本地范围内保留副本,从而影响性能:http://jsperf.com/short-scope。对window的所有访问现在都必须在范围链中向下移动一级。与undefined一样,本地副本再次允许更积极的缩小。


旁注:

虽然这可能不是jQuery开发人员的意图,但是传入window允许库更容易地集成到服务器端Javascript环境中,例如node.js - 其中没有全局window对象。在这种情况下,只需要更改一行以将window对象替换为另一行。在jQuery的情况下,可以创建模拟window对象并将其传入以进行HTML抓取(像jsdom这样的库可以执行此操作)。

答案 2 :(得分:16)

其他人已解释undefinedundefined就像一个全局变量,可以重新定义为任何值。如果有人在某处写了undefined = 10,那么这种方法可以防止所有未定义的检查中断。无论变量 undefined的值如何,永远不会传递的参数都是真实的undefined

通过窗口的原因可以用以下示例说明。

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();

控制台记录了什么? window对象的值是对吗?错误! 10?错误!它记录undefined。 Javascript解释器(或JIT编译器)以这种方式重写它 -

(function() {
   var window; //and every other var in this function

   console.log(window);
   ...
   ...
   ...
   window = 10;

})();

但是,如果您将window变量作为参数,则没有var,因此没有意外。

我不知道jQuery是否正在这样做,但如果你因为某种原因在函数的任何地方重新定义window局部变量,那么从全局范围借用它是个好主意。

答案 3 :(得分:6)

传递

window以防万一有人决定在IE中重新定义窗口对象,我假设undefined也是如此,以防它稍后以某种方式重新分配。

该脚本中的顶级window只是命名参数“window”,这是一个更全局的参数,即全局window引用,以及此闭包中的代码将使用的参数。最后的window实际上是指定第一个参数传递的内容,在本例中是window的当前含义...希望你之前没有搞砸window发生了。

通过显示jQuery,插件.noConflict()处理中使用的最典型案例,可能更容易想到这一点,因此对于大多数代码,您仍然可以使用$,即使它意味着什么<在此范围之外的em>其他而不是jQuery

(function($) {
  //inside here, $ == jQuery, it was passed as the first argument
})(jQuery);

答案 4 :(得分:5)

使用1000000次迭代进行测试。这种本地化对性能没有影响。在1000000次迭代中甚至不是一毫秒。这根本没用。