对象/函数/类声明周围的括号是什么意思?

我对JavaScript和YUI都不熟悉。在YUI库的例子中,你可以找到这个结构的很多用法:

(function() {
var Dom = YAHOO.util.Dom,
Event = YAHOO.util.Event,
layout = null,
...
})();

我认为最后两个括号是在声明之后执行函数的。

... 但是前面围绕函数声明的圆括号呢?

我认为这是一个范围问题;这是为了将变量隐藏到外部函数和全局对象中。是吗?更一般地说,这些括号的机制是什么?

127553 次浏览

第一个括号表示运算的顺序。围绕函数定义的括号集的“结果”是函数本身,实际上,第二组括号执行该函数。

至于为什么它是有用的,我不是一个足够的JavaScript向导有任何想法。: P

它是一个自动执行的匿名函数。第一组圆括号包含要执行的表达式,第二组圆括号执行这些表达式。

当试图从父名称空间隐藏变量时,它是一个有用的构造。函数中的所有代码都包含在函数的私有作用域中,这意味着它根本不能从函数外部访问,这使得它真正是私有的。

看到的:

http://en.wikipedia.org/wiki/Closure_%28computer_science%29

< a href = " http://peter.michaux。ca /文章/ javascript-namespacing noreferrer“rel = > http://peter.michaux.ca/articles/javascript-namespacing < / >

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

这是怎么回事?在函数add_gen中,您创建了另一个函数,该函数将简单地将数字n添加到其参数中。诀窍是在函数形参列表中定义的变量充当词法范围的变量,就像用var定义的变量一样。

返回的函数是add_gen函数的在括号之间定义,因此即使在add_gen函数完成执行之后,它也可以访问n的值,这就是为什么在执行示例的最后一行时,你会得到5。

借助函数参数的词法作用域,您可以解决在匿名函数中使用循环变量引起的“问题”。举个简单的例子:

for(var i=0; i<5; i++) {
setTimeout(function(){alert(i)}, 10);
}

“预期的”结果可能是从0到4的数字,但是您得到了4个5的实例。这是因为setTimeout中的匿名函数和for循环使用了完全相同的 变量,所以当函数被求值时,将为5。

通过使用问题中的技术和函数参数是词法范围这一事实,您可以得到预期的结果。(我在其他的答案中使用了这种方法)

for(var i=0; i<5; i++) {
setTimeout(
(function(j) {
return function(){alert(j)};
})(i), 10);
}

在外部函数的直接求值中,你在每次迭代中创建了一个名为j的完全独立变量,并且的当前值将是这个变量的复制,因此你将得到第一次尝试时天真地期望的结果。

我建议你试着去理解http://ejohn.org/apps/learn/的优秀教程,以更好地理解闭包,这是我学到很多很多的地方。

...但是之前所有函数声明周围的圆括号呢?

具体来说,它使JavaScript解释'function(){…构造为内联匿名函数表达式。如果省略括号:

function() {
alert('hello');
}();

你会得到一个语法错误,因为JS解析器会看到'function'关键字,并假设你正在开始一个形式为声明的函数:

function doSomething() {
}

...你不能有一个没有函数名的函数语句。

函数表达式和函数语句是两种不同的结构,以非常不同的方式处理。不幸的是,语法几乎完全相同,所以这不仅让程序员感到困惑,甚至解析器也难以分辨您的意思!

看到这个问题。如果你使用函数名,第一组圆括号是不必要的,但是一个没有名字的函数需要这个结构,圆括号可以让程序员在浏览代码时意识到他们看到了一个自调用函数(参见一个博主的最佳实践建议)。

关于这个问题的几点考虑:

  • < p >括号:

    浏览器(引擎/解析器)将关键字函数与

    [optional name]([optional parameters]){...code...}
    

    因此,在function(){}()这样的表达式中,最后一个括号没有意义。

    现在想想

    name=function(){} ; name() !?
    

Yes, the first pair of parenthesis force the anonymous function to turn into a variable (stored expression) and the second launches evaluation/execution, so ( function(){} )() makes sense.

  • The utility: ?

    1. For executing some code on load and isolate the used variables from the rest of the page especially when name conflicts are possible;

    2. Replace eval("string") with

      (new Function("string"))()

    3. Wrap long code for " =?: " operator like:

      result = exp_to_test ? (function(){... long_code ...})() : (function(){...})();

我想继续安迪·休谟和其他人说过的话

匿名函数周围的“()”是ECMA规范:http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf第11.1.6节中定义的“分组操作符”。

从文件中逐字逐句摘录:

11.1.6分组操作符

产品PrimaryExpression:(表达式)的计算方法如下:

  1. 返回计算表达式的结果。这可能是Reference类型。

在这种情况下,函数被视为表达式。