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

2022-08-29 23:59:19

我是JavaScript和YUI的新手。在 YUI 库示例中,您可以找到此构造的许多用法:

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

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

...但是函数声明周围的前一组括号呢?

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


答案 1

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

在尝试从父命名空间中隐藏变量时,它是一个有用的构造。函数内的所有代码都包含在函数的私有范围内,这意味着它根本无法从函数外部访问,使其真正私有。

看:

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

http://peter.michaux.ca/articles/javascript-namespacing


答案 2

安迪·休谟(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 的数字,但您会得到四个 5 的实例。发生这种情况是因为 setTimeout 和 for 循环中的匿名函数使用完全相同i 变量,因此当函数被计算时,i 将是 5。

您可以通过在问题中使用技术和函数参数在词法上限定范围的事实来获得天真的预期结果。(我在其他答案中使用了这种方法)

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

通过对外部函数的立即求值,您将在每次迭代中创建一个名为j的完全独立的变量,并且i的当前值将被复制到此变量中,因此您将获得第一次尝试时天真期望的结果。

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