9

在许多书籍/博客文章中,自调用匿名函数模式是这样写的:

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

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

将调用移动到包含函数的括号中。

例如将其更改为此作品:

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

问题

  1. 为什么第一个实现对 JSLint 来说不够好?有什么区别?
  2. 首选形式是什么?JSLint 总是正确的吗?
  3. 为什么它有效?毕竟function(){}()会抛出 aSyntaxError: Unexpected token (
    但是用括号包裹它会突然起作用吗?例如( function(){}()) - 工作正常
    (毕竟这是 JavaScript,而不是 Lisp,那么包装括号对 ohterwise 语法错误有什么影响?)

编辑:这是对此的跟进(虽然我不会说完全重复):JSLint 错误:“将调用移动到包含函数的括号中”,所以我的主要问题是#3,为什么它完全有效?

4

2 回答 2

6

我不知道 Crockford 的观点是如何形成的,但我可以解释为什么用括号括起来是有效的。

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");
}();
于 2013-04-16T00:47:52.537 回答
1

1.

显然这是约定的问题。第一个示例显示“缺乏约定”(source)。至于实际差异,则没有。两者都将毫无错误地执行。

2.

在这种情况下,我更喜欢您的第一个示例,但这只是我的惯例。JSLint 通常是正确的。因此,如果您想遵循他们的命名约定,那么当它显示基于约定的警告时,遵守约定是有意义的。

3.

这是有效的,因为包装 a 的function(){}内部()使其成为一个表达式,一旦与 final 配对,()就会立即调用它。因此,您有一个立即调用的函数表达式。

于 2013-04-16T00:47:52.807 回答