4

Airbnd 建议我这样做:

!function() {
  // ...
}();

因为:

这确保了如果格式错误的模块忘记包含最后的分号,则在连接脚本时不会在生产中出错。

bang 让我可以绕过语言的语法规则:

// Evaluated in Chromium 34 console.
function(){}(); // => SyntaxError: Unexpected token (
!function(){}(); // => true

当连接其他模块时,爆炸似乎起到了作用:

!function(){}();function(){}(); // => SyntaxError: Unexpected token (
!function(){}();!function(){}(); // => true
(function(){}());!function(){}(); // => true

然而,它似乎实际上并不“安全”,因为如果其他人在他的脚本末尾没有分号:

!function(){}()!function(){}(); // => SyntaxError: Unexpected token !
(function(){}())!function(){}(); // => SyntaxError: Unexpected token !

似乎以分号开头的 IIFE 更好。

;(function() {
  // ...
}());

!function(){}();(function(){}()); // => undefined
(function(){}());(function(){}()); // => undefined
!function(){}();;(function(){}()); // => undefined
(function(){}());;(function(){}()); // => undefined

我错过了什么吗?使用 bang "!" 真的可以接受吗?函数或前导分号“;” IIFE 真正优越是因为它们的连接方式吗?

4

3 回答 3

8

那里总是有 IEFE。是否将它们括在括号中或在它们前面加上 a!是您的选择,并且没有任何区别。您需要其中之一来强制将函数解析为表达式。请参阅javascript 函数领先 bang !有关详细信息的语法

是否在整个构造前加上 a;以防止错误与编写不佳的脚本连接(JavaScript 库中的前导分号是做什么的?)是完全不相关的。您可以根据需要混合模式:

 !function(){…}() // not safe for arbitrary concatenation
 (function(){…}()) // not safe for arbitrary concatenation either
;!function(){…}()
;(function(){…}())

但是,有一种连接情况,()vs!确实会有所不同:如果连接两个脚本,以便在它们之间有一个换行符,并且前者不以分号结尾。这确实允许自动插入分号- 当下一行确实以一声开头时!

1 + 2             // script A
!function(){…}(); // script B
// works!

1 + 2              // script A
(function(){…}()); // script B
// runtime error: "2 is not a function" (or whatever the previous line ends in)

我们了解到:始终以分号结束您的脚本。使用智能串联。如果您需要安全地避免哑连接,请以分号开始您的脚本。

于 2014-06-05T19:11:23.890 回答
4

!实际上与在连接文件时防止丢失分号无关。它通常用于强制将以下函数定义评估为表达式,而不是声明

另一方面,前导分号结束可能出现在它之前的任何“开放”表达式语句。

但是,如果您按照说明进行操作,则似乎!它是该行中的第一个字符就足够了。显然,由于 ASI,JS 会在前面添加一个分号。但是,这似乎是一种更脆弱的方法,因为您可能无法完全控制模块的连接方式。使用分号绝对“更安全”。

于 2014-06-05T18:38:09.173 回答
-2

实际上这也有效:

;!function() {
  // ...
}();

!function(){}()!function(){}(); // => SyntaxError: Unexpected token !
!function(){}();!function(){}(); // => true
(function(){}());!function(){}(); // => true
!function(){}();;!function(){}(); // => true
(function(){}());;!function(){}(); // => true

因此,正如我在问题的最后一段中心不在焉地假设的那样,IIFE 并不比 bang 函数更好。无论您使用 bang 函数还是 IIFE,在它们之前的前导分号都是一种很好的防御技术。

于 2014-06-05T18:49:26.887 回答