【问题标题】:What is the difference between those self-executing anonymous function (aka IIFE) implementation那些自执行匿名函数(又名 IIFE)实现之间有什么区别
【发布时间】:2013-04-08 06:14:04
【问题描述】:

在许多书籍/blog posts 中,自调用匿名函数模式是这样写的:

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

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

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

例如将其更改为此作品:

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

问题

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

编辑:这是对此的后续(虽然我不会说完全重复):JSLint error: "Move the invocation into the parens that contain the function",所以我的主要问题是#3,为什么它完全有效?

【问题讨论】:

标签: javascript


【解决方案1】:

我不知道 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");
}();

【讨论】:

  • 所显示的模式都不是 FunctionDeclaration,虽然这确实解决了 #3,但它确实是切线..
  • 我不明白第一个不是 FunctionDeclaration。根据the spec,FunctionDeclration 是function Identifier ( FormalParameterListopt ) { FunctionBody },我的示例匹配。
  • (function() {})()(第一种形式)vs.(function() {}())(第二种形式)vsfunction(){}()(问题#3)。当然,问题 #3 无法解决上下文,因为 x = function(){}() 将再次有效(而不是 FunctionDeclaration)。
  • 哦,您的意思是问题中的示例。确实如此,但这种区别对于解释 (3) 是必要的。
  • 请注意,还有其他方法可以强制将函数解释为表达式,例如!function(){}();
【解决方案2】:

1.

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

2.

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

3.

之所以有效,是因为将function(){} 包裹在() 中使其成为一个表达式,一旦与最终的() 配对,就会立即调用它。因此,您有一个立即调用的函数表达式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-29
    • 2013-12-07
    • 2023-03-12
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 2019-09-03
    • 2021-12-12
    相关资源
    最近更新 更多