你有没有看过 jQuery 1.4 源代码,并注意到它是如何以下列方式封装的:
(function( window, undefined ) {
//All the JQuery code here
...
})(window);
我读过一篇关于JavaScript Namespacing的文章和另一篇名为“An Important Pair of Parens”的文章,所以我知道这里发生了什么。
但我以前从未见过这种特殊的语法。在那里做什么 undefined
?为什么 window
需要通过然后再次出现?
答案 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)
其他人已解释undefined
。 undefined
就像一个全局变量,可以重新定义为任何值。如果有人在某处写了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次迭代中甚至不是一毫秒。这根本没用。