【问题标题】:Purpose of the outer extra parenthese on JavaScript closure function [duplicate]JavaScript闭包函数外部额外括号的目的[重复]
【发布时间】:2013-04-03 14:16:15
【问题描述】:

下面的 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
}());

【问题讨论】:

  • 您也可以在它前面加上 void 或算术运算符。
  • @杰克。请详细说明。
  • void function() { dostuff(); }();

标签: javascript closures


【解决方案1】:

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

function(){...}();

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

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

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

var f = function() {...}

而函数声明看起来像:

function f() {...}

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

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

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

【讨论】:

  • 所以,它有时是必需的,有时不是基于给定的引擎,我应该一直这样做吗?
  • 是的。这是一个非常强大的约定。您可能应该一直这样做......除非您找到其他流行的方式来让引擎清楚,并且想要支持它。
  • FF 没有它会导致 s 语法错误。
【解决方案2】:

首先,我必须澄清:

(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

【讨论】:

  • 很好的解释。我希望我能投票更多。我相信其他答案更好地满足了我的具体问题,但这澄清了我的一个更大的谜团。 (function (c, d) {console.log(a,b,c,d);}(a, b)); 将显示 a,b,a,b。谢谢你,我明白了!谢谢
【解决方案3】:

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

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

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

或者,甚至:

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

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

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

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

【讨论】:

    【解决方案4】:

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

    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 的函数都是函数表达式。

    【讨论】:

      猜你喜欢
      • 2012-08-01
      • 1970-01-01
      • 2013-11-02
      • 1970-01-01
      • 1970-01-01
      • 2015-04-05
      • 1970-01-01
      • 2019-02-13
      • 1970-01-01
      相关资源
      最近更新 更多