JavaScript闭包函数上外部额外括号的用途

时间:2013-04-03 14:16:15

标签: javascript closures

以下JavaScript闭包函数的外部额外括号的用途是什么?在其他帖子中我被告知它们并不是绝对必要的,但是它们是一个约定,以明确函数的结果被传递,而不是函数本身。来自http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html的以下引用 然而,冲突。哪个是对的?

  

注意匿名函数周围的()。这是必需的   语言,因为以令牌函数开头的语句是   始终被认为是函数声明。包括()创建一个   而是函数表达式。

(function () {
    // ... all vars and functions are in this scope only
    // still maintains access to all globals
}());

4 个答案:

答案 0 :(得分:6)

我认为不同的引擎有不同的解释方式

function(){...}();

因此,对所有引擎来说,最流行和最常用的方法是将代码分组到括号中。

(function(){...}());

与此同时,你引用的内容非常有趣。函数表达式可能会出现:

var f = function() {...}

虽然函数声明如下:

function f() {...}

你看到解析器如何通过查看第一个令牌来轻松/方便地区分它?

IF TOKEN1 EQ "function": FXN DECLARATION
ELSE: FXN EXPRESSION

但是你的(立即调用的)函数是一个函数声明是没有意义的(它不会被重用,你不想让它被提升,或者在命名空间中等等。因此,添加一些无关紧要的括号是指示它是函数表达式的好方法。

答案 1 :(得分:5)

首先,我必须清理:

(function () {

}());

等同于

(function () {

})();

以及(Backbone.js使用它)

(function(){

}).call(this);

其次,如果您打算以这种方式使用它,那么它不是匿名/闭包函数。其立即调用的函数表达式

如果将返回的上下文分配给变量,它将充当闭包(因为它不会立即被调用)。如果你需要一个静态类(当没有实例化时可以访问属性和方法),这种方法很有用。例如:

var stuff = (function(){

    // AGAIN: its not an IIFE in this case

    function foo() // <- public method
    {
        alert('Jeeez');
    }

    return {
       foo : foo,
    }
})();


stuff.foo(); //Alerts Jeeez
  

下面的外部额外括号的目的是什么?   JavaScript闭包函数?

目的不常见而且非常奇怪 - 它都是关于函数参数的。 例如,

(function(window, document){ // <- you see this? 2 "arguments"

  alert(arguments.length); // 0!

})();

但如果我们将它们传递给那个外部括号

(function(/* So its not for arguments */ ){

  alert(arguments.length); // 2

})(window, document); // <- Instead we pass arguments here

答案 2 :(得分:4)

额外的周围括号消除了常规函数声明中的函数表达式。

虽然额外的括号是标准做法,但通过这样做可以实现同样的目的:

void function() {
    // do stuff
}();

或者,甚至:

+function() {
    // do stuff
}();

尽管在这两种选择中,我更喜欢void符号,因为在大多数情况下,我们并不关心立即调用的返回值。

不需要括号的其他地方是预期表达式时:

setTimeout(function() {
    return function() {
        alert('hello');
    }
}(), 1000);

答案 3 :(得分:1)

它们是必需的,因为解析器在看到

时进入函数声明模式
function

语句上下文中

function标记之后,它期望该函数的名称,因为函数声明必须包含该函数的名称。但它代替了(而不是名称,所以这是一个语法错误。

我认为,它可以回溯并且毫不含糊地将其视为函数表达式,但事实并非如此。

<小时/> var module = XXX

在上文中,XXX位于表达式上下文中,如果出现function,则将其视为函数表达式的开头。函数表达式不必具有 函数的名称,因此(之后function出现var module = function(){}(); 不是语法错误。

所以你可以写:

function(){}()

但不是

(XXX)
!XXX
~XXX
+XXX

//This doesn't work however:
{YYY} //the braces are delimiting a block, and inside block you start in
      //a statement context

您可以使用许多技巧使上面的表达式成为:

XXX

XXX在表达式上下文中,因为它用括号括起来或跟在一元运算符之后,因此替换{{1}}的任何函数都是函数表达式。