在很多书/ blog posts中,自调用匿名函数模式的方式如下:
(function() {
var foo = 'bar';
})();
但是,对此运行JSLint会出现此错误:
将调用移动到包含该函数的parens中。
e.g。改变它的工作原理:
(function() {
var foo = 'bar';
}());
问题
function(){}()
之后抛出一个SyntaxError: Unexpected token (
˙但用parens包裹它会让它突然间起作用?例如( function(){}()
) - 工作正常
编辑:这是对此的一些后续(我不会说完全重复):JSLint error: "Move the invocation into the parens that contain the function",所以我的主要问题是#3,为什么它一直有效?
答案 0 :(得分:5)
我不知道Crockford的意见是如何形成的,但我可以解释为什么包裹在parens中。
JavaScript中的函数function() { ... }
语法可以表示两种不同的东西:函数声明或函数表达式。
函数声明是一个语句,用于在指定名称下定义当前作用域内的函数。
function example() {
alert("Hello World");
}
example();
函数表达式是一个表达式,它计算为新的Function
实例。
var secondExample = function example() {
alert("Hello World");
};
secondExample();
example(); // <-- throws an Error: example is not defined.
语法的出现是函数声明还是函数声明取决于解析器的期望。 JavaScript的解析器很简单。它不会向前看并注意到函数后跟()
,因此它应该将其视为表达式。它只是在行的开头看到function
,因此将其视为一个语句,当它跟随()
时会导致语法错误。当你将它包装在括号中时,解析器会期望一个表达式,并且它可以工作。
用括号括起来(无论你放在哪里)都是最清楚的方法,但是任何导致解析器期望表达式的东西都会起作用。例如,按位NOT运算符~
:
~function() {
alert("Hello World");
}();
答案 1 :(得分:1)
1
显然这是惯例的问题。第一个例子显示“缺乏约定”(source)。就实际差异而言,没有。两者都会毫无错误地执行。
2
在这种情况下,我更喜欢你的第一个例子,但这只是我的惯例。 JSLint通常是正确的。因此,如果您想遵循它们的命名约定,那么当它显示基于约定的警告时,符合约定是有意义的。
3
这样做是因为将function(){}
包裹在()
内部使其成为表达式,一旦与最终()
配对,就立即调用它。因此,您有一个立即调用的函数表达式。