(function( window, undefined ) {
//All the JQuery code here
...
})(window);
我读过一篇有关JavaScript的文章Namespacing和另一个叫做“一对重要的父母”,所以我知道这里发生了什么。
但是我以前从未见过这种特殊的语法。
undefined
在那做什么?为什么要传递window
,然后再次出现在末尾?#1 楼
undefined是普通变量,可以使用undefined = "new value";
进行简单更改。因此,jQuery创建了一个真正的undefined本地“ undefined”变量。出于性能原因,将window变量设置为local。因为当JavaScript查找变量时,它首先会遍历局部变量,直到找到变量名为止。当找不到它时,JavaScript将遍历下一个范围等,直到它对全局变量进行过滤。因此,如果将window变量设为本地,JavaScript可以更快地查找它。
更多信息:加快JavaScript的速度-Nicholas C. Zakas
评论
谢谢!这是一个非常有用的视频。我认为您需要编辑响应以说“ window变量设为本地”。我确实认为这是最好的答案。我数了一下,发现在JQuery源代码中窗口对象至少被调用了17次。因此,将窗口移到“本地合并范围”中将产生重大影响。
– dkinzer
2010-4-26 20:47
@DKinzer哦,是的,您是对的,当然它是本地化的。很高兴可以为您提供帮助=)
– Vincent
2010-4-27的15:00
根据此更新的测试jsperf.com/short-scope/5,通过jQuery获取窗口常量时,传递“窗口”实际上要慢一些,这对Safari尤其不利。因此,尽管“未定义”有一个用例,但我不太相信“窗口”在所有情况下都特别有用。
– hexalys
13年4月28日在10:38
这对于减少代码也有积极作用。因此,最小化器可以用较短的名称替换“窗口”和“未定义”的每种用法。
–TLindig
13年6月6日在8:05
@ lukas.pukenis当您要建立数以百万计的网站使用的图书馆时,明智的做法是不要对疯子的行为做出假设。
– JLRishe
2014年9月1日在18:56
#2 楼
未定义通过将
undefined
声明为参数,但从不传递任何值,可以确保始终未定义,因为它只是全局范围内的变量,可以覆盖。这使a === undefined
可以安全替代typeof a == 'undefined'
,从而节省了一些字符。它还使代码更加简化,例如可以将undefined
缩短为u
,从而节省更多字符。Window
将
window
作为参数传递可以保持在本地范围内复制,这会影响性能:http://jsperf.com/short-scope。现在,对window
的所有访问都必须在范围链上移动一级。与undefined
一样,本地副本再次允许更积极的缩小。旁注:
window
中的允许将该库更轻松地集成到服务器端Javascript环境中,例如node.js-其中没有全局window
对象。在这种情况下,只需更改一行即可将window
对象替换为另一行。对于jQuery,可以创建一个模拟的window
对象并将其传入以进行HTML抓取(jsdom之类的库可以做到这一点)。评论
+1代表Minification,希望我能为jsperf +2-最小版本为(function(a,b){})(window); -a和b比window短得多并且未定义:)
– gnarf
2011-2-9 13:25
+1我之前听说过作用域链,但是忘记了这个词。谢谢!
– alex
2011-2-9 13:25
这也是使用void(0)的另一种选择,它的意思是出于相同的原因:void(0)是获取未定义值的安全方法。
– glmxndr
2011-2-9 13:26
“您所说的”是指另一个问题:stackoverflow.com/questions/4945265/…
– gnarf
2011-2-9 13:46
@gnarf,感谢您提出问题合并的通知。我将编辑我的答案以使其更有意义;)
–大卫·唐(David Tang)
2011-2-9 13:48
#3 楼
其他人已经解释了。undefined
就像可以重新定义为任何值的全局变量。如果有人在某处写了“ undefined
”,此技术可以防止所有未定义的检查都中断。不管变量undefined = 10
的值如何,保证永远不会传递的参数是真实的undefined
。可以通过以下示例说明传递窗口的原因。
(function() {
console.log(window);
...
...
...
var window = 10;
})();
控制台记录什么?
undefined
对象的值对吗?错误! 10个?错误!它记录window
。 Javascript解释器(或JIT编译器)以这种方式重写它-(function() {
var window; //and every other var in this function
console.log(window);
...
...
...
window = 10;
})();
但是,如果将
undefined
变量作为参数,则不会有var,因此不会感到意外。 我不知道jQuery是否正在执行此操作,但是如果出于某种原因要在函数中的任何位置重新定义
window
局部变量,则最好从全局范围中借用它。 >#4 楼
window
是这样传入的,以防万一某人决定在IE中重新定义窗口对象,我假设undefined
也是一样,以防以后以某种方式重新分配。脚本只是将参数命名为“ window”,该参数比全局
window
引用更本地化,并且此闭包内部的代码将使用什么。最后的window
实际上指定了第一个参数要传递的内容,在这种情况下,是window
的当前含义...希望您在此之前不会搞砸window
。此通过显示在jQuery中使用的最典型的情况,插件
window
处理,可能会更容易想到,因此对于大多数代码,您仍然可以使用.noConflict()
,即使它意味着超出此范围的$
之外:(function($) {
//inside here, $ == jQuery, it was passed as the first argument
})(jQuery);
评论
谢谢。这很有道理。虽然,我认为答案是这与@ C.Zakas说的结合。
– dkinzer
2010-4-26 20:50
@DKinzer恐怕我不是C.扎卡斯;)
– Vincent
2010-4-27的15:02
@Vincent,对此感到抱歉:-)
– dkinzer
2010-4-27的15:14
#5 楼
经过1000000次迭代测试。这种本地化对性能没有影响。 1000000次迭代中甚至没有一个毫秒。这根本没用。评论
更不用说,闭包包含所有变量以及函数实例,因此,如果闭包中有100个字节,而1000个实例中有100kb的更多内存。
– Akash Kava
13年7月31日在8:50
@AkashKava和@Semra,我认为此测试不能真正解释为什么您会在现实世界中通过窗口。仅当您具有深度嵌套的闭包(沿范围链进一步访问该变量)时,才能看到性能提升。显然,如果您的函数与变量在作用域链上仅相距仅一步之遥,您将不会获得太多收益。但是如果它在下面,并且需要打开窗口,您可能会看到本地副本有所帮助。
– Gabereal
2014年12月2日在21:42
@gabereal新的JavaScript引擎会在编译时自行解决闭包,在运行时闭包不会提高性能。我怀疑是否会有可衡量的性能提升,如果您如此有信心,可以创建jsperf示例来演示性能。我们获得的唯一性能是隔离闭包,从而实现更好的缩小效果,从而减小大小,并通过更快的脚本下载和解析来实现性能。
– Akash Kava
2014年12月4日上午10:59
@AkashKava是什么让您觉得我很自信?我只是说“可能会有所收获”和“我不认为”。我可以创建一个测试,但是我宁愿不这样做,因为我从不使用这种模式。您能否解释“在编译时解析闭包”的含义?相对于其他选择呢? JavaScript引擎之前的功能有何不同?
– Gabereal
2014年12月4日21:36
找到一个代码,该代码在最后固化窗口但未在函数的参数中输入,这是什么意思?它确保即使我假设没有任何窗口参数,参数也可以遵循原始全局范围对象。
– Webwoman
19年1月22日在23:10
评论
我想补充一下,保罗·爱尔兰(Paul Irish)在此视频中谈到了这一点:paulirish.com/2010/10-things-i-learned-from-the-jquery-source@Bergi,您将我的问题标记为另一个问题的重复,但是在重复之前将近一年,我问了这个问题。演员阵容应该与之相反。
@dkinzer:这不是关于早些被问到,而是关于最高质量的答案。诚然,在这种情况下,并驾齐驱,但我发现CMS的答案是最好的答案。不过请访问chat.stackoverflow.com/rooms/17进行讨论
另请参见使用(function(window,document,undefined){…})(window,document)有什么好处?