为什么这个匿名函数调用中缺少括号?

时间:2015-07-08 07:59:55

标签: javascript anonymous-function

我正在读这本书,它有这个代码示例

function getFunction() {
    var result = [];
    for (var i = 0; i < 10; i++) {
        result[i] = function(num) {
            return function() {
                console.log("this is " + num);
            }
        }(i);
    };

    return result;
}

它工作正常,但为什么这里的匿名函数没有包含在像(function(...))(i);这样的括号中?在哪些情况下可以在匿名函数中省略括号?

4 个答案:

答案 0 :(得分:18)

由于函数声明和函数表达式的语法是相同的,因此JS会从函数周围的代码中告诉您使用哪一个。

要阻止它成为函数声明,您需要在表达式中使用它。将它括在括号中将会做到这一点,但在它前面加上=也是如此(与许多其他运算符一样)。由于此处有=,因此括号是不必要的。

答案 1 :(得分:8)

由于它被用作赋值运算符=的第二个操作数,因此JS引擎可以将其视为函数表达式。

当您单独定义匿名函数时不是这种情况:在这种情况下,您需要帮助引擎将其视为表达式,而不是声明。

答案 2 :(得分:4)

常规函数声明如下所示:

function FuncName() { doSomething(); }

然后你可以像这样调用这个函数:

FuncName();

匿名函数非常相似:

var FuncName = function YouCanEvenPutANameHereAndItWillBeIgnored() { doSomething(); }

如果常规函数和匿名函数的语法相同,那么JS如何区分它们?它从上下文中推断出你的意思。这就是为什么这个瞬间调用函数表达式无法工作的原因:

function(s) { console.log(s); } ('abc');

JS解析器从左侧读取它。该行以function开头,因此JS猜测它是一个常规函数声明,并期望它以}结尾。但是,在函数之后有('abc'),JS会抛出错误。

要修复它,你必须欺骗JS将该函数解析为匿名函数。要做到这一点,你必须使它成为表达式的一部分。最流行的方式是:

(function(s) { console.log(s); }) ('abc');

但还有其他方法。它们的可读性较差,但它们也有效。

( function(s) { console.log(s); } ('abc') );
+function(s) { console.log(s); } ('abc');
-function(s) { console.log(s); } ('abc');
1 * function(s) { console.log(s); } ('abc');

在你的情况下,该函数已经是表达式的一部分,因此不需要添加括号。

答案 3 :(得分:2)

这些是立即调用的函数表达式(IIFE)。它们可以在任何需要表达式的地方使用。示例位于等号的右侧或比较运算符的任一侧,或者甚至作为另一个函数的参数。需要括号的地方是,如果在不期望表达式的情况下使用括号。例如在以下示例中

var a=1;
(function(b){
  a=b;
})(2);
console.log(a);

哪个输出2。

在任何地方,预期表达式都是等价的

function(a){....}(b);

(function(a){....})(b);

(function(a){....}(b));

然而,括号被认为是最佳实践,因为它们提示&#34;提示&#34;事实上它是一个立即调用的函数,而不必向下滚动到函数的末尾。