这个 JavaScript/jQuery 语法是如何工作的: (函数(窗口,未定义){})(窗口) ?

您是否曾经深入研究过 JQuery 1.4源代码,并注意到它是如何被以下方式封装的:

(function( window, undefined ) {


//All the JQuery code here
...


})(window);

我读过一篇关于 JavaScript 命名空间的文章,还有一篇叫做“ 一对重要的父母”,所以我知道这里发生了什么。

但我以前从未见过这种特殊的语法。那个 undefined是干什么的?为什么 window需要被传递,然后再次出现在结尾?

41869 次浏览

为了防止有人决定在 IE 中重新定义窗口对象,我假设 window也是这样传入的,以防以后它以某种方式被重新分配。

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

通过展示 jQuery 中使用的最典型的例子,即插件 .noConflict()处理,这可能更容易想到,因此对于大多数代码,你仍然可以使用 $,即使它意味着 其他jQuery更超出这个范围:

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

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

由于性能原因,窗口变量被设置为本地变量。因为当 JavaScript 查找变量时,它首先遍历本地变量,直到找到变量名。当没有找到它时,JavaScript 会进入下一个作用域等等,直到它过滤掉全局变量。因此,如果窗口变量是本地的,JavaScript 可以更快地查找它。 更多信息: 加速你的 JavaScript-Nicholas C. Zakas

其他人解释了 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局部变量,那么从全局范围借用它是一个好主意。

不确定

通过声明 undefined作为参数,但从不向其传递值,可以确保它始终是未定义的,因为它只是全局作用域中的一个可以被覆盖的变量。这使得 a === undefined成为 typeof 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这样的库可以做到这一点)。

通过1000000次迭代进行测试。这种局部化对性能没有影响。在1000000次迭代中甚至没有一毫秒。这根本没用。