为什么这个匿名函数调用中缺少括号?
Why is the parenthesis missing in this anonymous function call?
我正在读这本书,它有这个代码示例
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);
?匿名函数在哪些情况下可以省略括号?
由于函数声明和函数表达式的语法是相同的,JS会从函数周围的代码中判断出你使用的是哪一个。
要阻止它成为函数声明,您需要在表达式中使用它。将它括在括号中可以做到这一点,但在它前面加上 =
也可以(许多其他运算符也是如此)。由于这里有一个=
,括号是不必要的。
因为它被用作赋值运算符的第二个操作数=
JS引擎肯定可以将其视为函数表达式。
独立定义匿名函数时情况并非如此:在这种情况下,您需要帮助引擎将其视为表达式,而不是语句。
这些是立即调用的函数表达式 (IIFE)。它们可以用在任何需要表达式的地方。示例位于等号的右侧或比较运算符的任一侧,甚至作为另一个函数的参数。需要括号的地方是在不需要表达式的地方使用它们。比如下面的例子
var a=1;
(function(b){
a=b;
})(2);
console.log(a);
输出 2.
任何需要表达式的地方,下面的表达式都是等价的
function(a){....}(b);
(function(a){....})(b);
(function(a){....}(b));
然而,括号被认为是最佳实践,因为它们 "hint" 事实上它是一个立即调用的函数,而无需向下滚动到函数的末尾。
常规函数声明如下所示:
function FuncName() { doSomething(); }
然后你可以这样调用这个函数:
FuncName();
匿名函数非常相似:
var FuncName = function YouCanEvenPutANameHereAndItWillBeIgnored() { doSomething(); }
如果说普通函数和匿名函数的语法是一样的,那么JS是怎么区分的呢?它从上下文中推断出你的意思。这就是为什么这个 Instantly Invoked Function Expression 不起作用的原因:
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');
在您的情况下,函数已经是表达式的一部分,因此无需添加括号。
我正在读这本书,它有这个代码示例
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);
?匿名函数在哪些情况下可以省略括号?
由于函数声明和函数表达式的语法是相同的,JS会从函数周围的代码中判断出你使用的是哪一个。
要阻止它成为函数声明,您需要在表达式中使用它。将它括在括号中可以做到这一点,但在它前面加上 =
也可以(许多其他运算符也是如此)。由于这里有一个=
,括号是不必要的。
因为它被用作赋值运算符的第二个操作数=
JS引擎肯定可以将其视为函数表达式。
独立定义匿名函数时情况并非如此:在这种情况下,您需要帮助引擎将其视为表达式,而不是语句。
这些是立即调用的函数表达式 (IIFE)。它们可以用在任何需要表达式的地方。示例位于等号的右侧或比较运算符的任一侧,甚至作为另一个函数的参数。需要括号的地方是在不需要表达式的地方使用它们。比如下面的例子
var a=1;
(function(b){
a=b;
})(2);
console.log(a);
输出 2.
任何需要表达式的地方,下面的表达式都是等价的
function(a){....}(b);
(function(a){....})(b);
(function(a){....}(b));
然而,括号被认为是最佳实践,因为它们 "hint" 事实上它是一个立即调用的函数,而无需向下滚动到函数的末尾。
常规函数声明如下所示:
function FuncName() { doSomething(); }
然后你可以这样调用这个函数:
FuncName();
匿名函数非常相似:
var FuncName = function YouCanEvenPutANameHereAndItWillBeIgnored() { doSomething(); }
如果说普通函数和匿名函数的语法是一样的,那么JS是怎么区分的呢?它从上下文中推断出你的意思。这就是为什么这个 Instantly Invoked Function Expression 不起作用的原因:
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');
在您的情况下,函数已经是表达式的一部分,因此无需添加括号。