这些自执行匿名函数(又名IIFE)实现之间有什么区别

时间:2013-04-16 00:39:40

标签: javascript

在很多书/ blog posts中,自调用匿名函数模式的方式如下:

(function() {
  var foo = 'bar';
})();

但是,对此运行JSLint会出现此错误:

  

将调用移动到包含该函数的parens中。

e.g。改变它的工作原理:

(function() {
  var foo = 'bar';
}());

问题

  1. 为什么第一个实现对JSLint来说不够好?有什么区别?
  2. 首选表格是什么? JSLint永远是对的吗?
  3. 为什么它会起作用?在所有function(){}()之后抛出一个SyntaxError: Unexpected token (˙但用parens包裹它会让它突然间起作用?例如 function(){}() - 工作正常
    (毕竟这是JavaScript,而不是Lisp,那么包装parens对ohterwise语法错误的影响是什么?)
  4. 编辑:这是对此的一些后续(我不会说完全重复):JSLint error: "Move the invocation into the parens that contain the function",所以我的主要问题是#3,为什么它一直有效?

2 个答案:

答案 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(){}包裹在()内部使其成为表达式,一旦与最终()配对,就立即调用它。因此,您有一个立即调用的函数表达式。