在YUI库的示例中,您可以找到许多使用此构造的示例:
(function() {
var Dom = YAHOO.util.Dom,
Event = YAHOO.util.Event,
layout = null,
...
})();
我认为最后一对括号是在声明函数后立即执行该函数。
... 但是围绕函数声明的前一组括号呢?
我认为这是范围的问题;它可以隐藏内部变量以外部函数和可能的全局对象。是吗?更普遍地说,这些括号的机制是什么?
在YUI库的示例中,您可以找到许多使用此构造的示例:
(function() {
var Dom = YAHOO.util.Dom,
Event = YAHOO.util.Event,
layout = null,
...
})();
我认为最后一对括号是在声明函数后立即执行该函数。
... 但是围绕函数声明的前一组括号呢?
我认为这是范围的问题;它可以隐藏内部变量以外部函数和可能的全局对象。是吗?更普遍地说,这些括号的机制是什么?
它是一个自执行的匿名函数。第一组括号包含要执行的表达式,第二组括号执行这些表达式。
当尝试隐藏变量以使其不被父命名空间访问时,它是一个有用的结构。函数内的所有代码都包含在函数的私有作用域中,意味着它不能从函数外部访问,使其真正成为私有的。
参见:
Andy Hume 已经 给出 了答案,我只想再添加一些细节。
使用这个结构,你正在创建一个具有自己的评估环境或闭包的匿名函数,然后立即对它进行评估。好处在于,你可以访问在匿名函数之前声明的变量,并且你可以在此函数中使用局部变量,而不会意外地覆盖现有变量。
使用var关键字非常重要,因为在JavaScript中,默认情况下每个变量都是全局的,但是使用关键字你可以创建一个新的、词法作用域变量,也就是说,它可以被代码在两个大括号之间看到。在你的例子中,你实际上是在为YUI库中的对象创建短别名,但它还有更强大的用途。
我不想让你没有代码示例,所以我将放置一个简单的示例来说明闭包:
var add_gen = function(n) {
return function(x) {
return n + x;
};
};
var add2 = add_gen(2);
add2(3); // result is 5
for(var i=0; i<5; i++) {
setTimeout(function(){alert(i)}, 10);
}
for(var i=0; i<5; i++) {
setTimeout(
(function(j) {
return function(){alert(j)};
})(i), 10);
}
在外部函数的立即评估中,每次迭代都会创建一个完全独立的变量j,并且i的当前值将被复制到该变量中,因此您将获得最初尝试时期望的结果。
我建议您尝试理解http://ejohn.org/apps/learn/上的优秀教程,以更好地理解闭包,那是我学到非常多的地方。
...但是之前所有函数声明周围的括号怎么办?
具体而言,它会使JavaScript将'function() {...}'结构解释为内联匿名函数表达式。如果您省略了括号:
function() {
alert('hello');
}();
您会得到一个语法错误,因为JS解析器会看到'function'关键字并假定您正在开始一个函数语句,形式如下:
function doSomething() {
}
如果没有函数名,就不能有函数语句。
函数表达式和函数语句是两种不同的构造方式,它们的处理方式也非常不同。不幸的是,它们的语法几乎完全相同,所以不仅程序员很容易混淆,解析器也很难分辨你想用哪个!
The parenthesis:
The browser (engine/parser) associates the keyword function with
[optional name]([optional parameters]){...code...}
So in an expression like function(){}() the last parenthesis makes no sense.
Now think at
name=function(){} ; name() !?
是的,第一对括号将匿名函数转化为变量(存储表达式),第二个则启动了评估/执行,因此(function(){})()是有意义的。
实用性: ?
用于在加载时执行某些代码,并将使用的变量与页面的其余部分隔离开来,特别是当可能存在名称冲突时;
将 eval("string") 替换为
(new Function("string"))()
用 " =?: " 运算符包装长代码,例如:
result = exp_to_test ? (function(){... long_code ...})() : (function(){...})();