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

Javascript 为什么在这个匿名函数调用中缺少括号?,javascript,anonymous-function,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); };

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

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 getFunction(){
var结果=[];
对于(变量i=0;i<10;i++){
结果[i]=函数(num){
返回函数(){
log(“这是”+num);
}
}(i) );
};
返回结果;
}

它工作正常,但是为什么这里的匿名函数没有像下面的
(函数(…)(i)那样被包装在括号中?在什么情况下匿名函数中可以省略括号?

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


要停止它作为函数声明,您需要在表达式中使用它。将它括在括号中可以做到这一点,但在它前面加一个
=
也可以(其他许多操作符也是如此)。因为这里有一个
=
,所以不需要括号

因为它被用作赋值运算符的第二个操作数
=
JS引擎可以肯定地将其视为函数表达式


当您定义匿名函数独立时,情况并非如此:在这种情况下,您需要帮助引擎将其视为表达式,而不是语句。

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

var a=1;
(职能(b){
a=b;
})(2);
控制台日志(a);
输出2

任何需要表达式的地方,以下内容都是等效的

函数(a){……}(b)

(功能(a){……})(b)

(函数(a){……}(b))


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

常规函数声明如下所示:

function FuncName() { doSomething(); }
FuncName();
然后您可以这样调用此函数:

function FuncName() { doSomething(); }
FuncName();
匿名函数非常相似:

var FuncName = function YouCanEvenPutANameHereAndItWillBeIgnored() { doSomething(); }
如果常规函数和匿名函数的语法相同,那么JS如何区分它们?它从上下文推断出你的意思。这就是为什么这个即时调用的函数表达式不起作用:

function(s) { console.log(s); } ('abc');
JS解析器从左边读取它。该行以
函数
开头,因此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');

在您的例子中,函数已经是表达式的一部分,因此不需要添加括号。

注意,还有其他方法可以使函数成为表达式。例如:
!function(){}()
0/function(){}()
或我最喜欢的
-function(){}()
也可以在其他地方看到。以
function
开头的行是一个解析错误,原因是该函数没有名称<代码>函数日志{console.log;}(函数{console.log;}('abc'))
声明一个函数
log
,然后记录
abc
。但是,将其包装在括号中,它将执行而不是声明。还有
通常用于将代码解析为表达式,它与自动分号插入交互良好。