9

下面 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

4 回答 4

6

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

function(){...}();

因此,对于所有引擎来说,最流行和接受的方式是将代码分组在括号中。

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

同时,您引用的内容提出了一个非常有趣的观点。函数表达式可能会:

var f = function() {...}

而函数声明看起来像:

function f() {...}

您看到解析器通过查看第一个标记来区分差异是多么容易/方便?

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

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

于 2013-04-03T14:24:26.213 回答
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
于 2013-04-03T15:26:43.170 回答
4

额外的括号消除了函数表达式与常规函数声明的歧义。

尽管额外的括号是标准做法,但可以通过这样做来实现相同的目的:

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

甚至:

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

不过,在这两种选择中,我更喜欢这种void表示法,因为在大多数情况下,我们并不真正关心立即调用的返回值。

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

setTimeout(function() {
    return function() {
        alert('hello');
    }
}(), 1000);
于 2013-04-03T14:29:16.343 回答
1

它们是必要的,因为解析器在看到时会进入函数声明模式

function

语句上下文中

functiontoken 之后,它需要函数的名称,因为函数声明必须包含函数的名称。但是它看到的(不是名称,所以这是一个语法错误。

我认为,它可以回溯并明确地将其视为函数表达式,但事实并非如此。


var module = XXX

在上面,XXX表达式上下文中,如果 afunction出现在那里,它被视为函数表达式的开始。函数表达式不必为函数命名,因此(出现在 . 之后并不是语法错误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的函数都是函数表达式。

于 2013-04-03T14:28:52.210 回答