【问题标题】:JavaScript Bang "!" Functions vs Leading Semi-Colon ";" IIFEsJavaScript 砰“!”函数与前导分号“;” IIFE
【发布时间】:2014-07-26 21:13:13
【问题描述】:

Airbnd suggests我这样做:

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

因为:

这样可以确保如果格式错误的模块忘记包含 final 分号 脚本获取时生产中没有错误 串联。

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 真正的优势在于它们的连接方式?

【问题讨论】:

    标签: javascript function concatenation iife


    【解决方案1】:

    那里总是有 IEFE。是否将它们括在括号中或在它们前面加上 ! 是您的选择,并且没有任何区别。您需要其中之一来强制将函数解析为表达式。详情请见javascript function leading bang ! syntax

    您是否在整个构造前加上 ; 以防止错误与编写不佳的脚本 (What does the leading semicolon in JavaScript libraries do?) 串联是完全不相关的。您可以根据需要混合模式:

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

    但是,有一种连接情况,()! 确实有所不同:如果连接两个脚本,则它们之间有一个换行符,而前者不以分号结尾。这确实允许automatic semicolon insertion to jump in - 当下一行确实以砰的一声开头时!

    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)
    

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

        其实这也行:

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

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

        【讨论】:

        • IIFE 的“不比 bang 函数好......”啊? IIFE 和“bang 函数”并不真正相关。 IIFE 是一种防止污染全局范围的结构。您可以在函数声明前放置一个!,以使其作为函数表达式进行评估...此外,“前导分号是破坏者 i>”是什么意思?
        • 1.在我的问题的最后一段中,我做出了错误的假设,即只能在 IIFE 前面加上分号。但是后来我意识到我可以很容易地在前面加上一个 bang 函数。 2. 在这种情况下,可以使用 bang 函数或 IIFE 来定义模块。 3. 如果没有前导分号,您会收到语法错误。我将更新这篇文章以澄清这一点。
        猜你喜欢
        • 1970-01-01
        • 2018-04-10
        • 1970-01-01
        • 2015-02-19
        • 2017-01-11
        • 2016-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多