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

dki*_*zer 153 javascript syntax jquery

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

(function( window, undefined ) {

  //All the JQuery code here 
  ...

})(window);
Run Code Online (Sandbox Code Playgroud)

我读过一篇关于JavaScript Namespacing的文章和另一篇名为" 一对重要的Parens "的文章,所以我知道这里发生了什么.

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

Vin*_*ent 159

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

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

  • @ lukas.pukenis当你创建一个在数百万个网站上使用的图书馆时,明智的做法就是不要对疯子会做什么做出假设. (2认同)

Dav*_*ang 54

未定义

通过声明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等库可以执行此操作).

  • 提及缩小的+1,希望jsperf可以+2 - 缩小版本是`(function(a,b){})(window);` - `a`和`b`比`更短window`和`undefined` :) (2认同)

Che*_*try 16

其他人解释说undefined.undefined就像一个全局变量,可以重新定义为任何值.这种技术是为了防止所有未定义的检查在有人写信的时候破坏undefined = 10.undefined无论变量 的值如何,保证永远不会传递的参数是真实的undefined.

通过窗口的原因可以通过以下示例来说明.

(function() {
   console.log(window);
   ...
   ...
   ...
   var window = 10;
})();
Run Code Online (Sandbox Code Playgroud)

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

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

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

})();
Run Code Online (Sandbox Code Playgroud)

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

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


Nic*_*ver 6

window就像有人决定在IE中重新定义窗口对象一样传入,我假设相同undefined,以防以后以某种方式重新分配.

window脚本中的顶部只是命名参数"window",这是一个更全局的参数,全局window引用以及此闭包中的代码将使用的参数.将window在年底实际上指定什么传递的第一个参数,在这种情况下,目前的意义window......希望是你还没有搞砸了window在这之前发生.

通过显示jQuery,插件.noConflict()处理中使用的最典型的情况,这可能更容易想到,因此对于大多数代码,您仍然可以使用$,即使它意味着除了此范围之外的其他内容jQuery:

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


Sem*_*mra 5

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

  • 更不用说,闭包带有所有变量以及函数实例,所以如果你有100个字节的闭包,1000个实例是100kb的更多内存. (2认同)