代码之家  ›  专栏  ›  技术社区  ›  Henrik Heimbuerger Kenneth Reitz

为什么调用匿名函数表达式有两种不同的语法?

  •  1
  • Henrik Heimbuerger Kenneth Reitz  · 技术社区  · 14 年前

    我刚读到 Ben Alman 的文章 Immediately-Invoked Function Expressions 想知道这一部分,他在哪里介绍函数表达式和闭包(还没有真正与IIFEs相关):

    // ...doesn't it stand to reason that the function expression itself can
    // be invoked, just by putting () after it?
    
    function(){ /* code goes here */ }();
    
    // This works! Well, almost. A minor JavaScript syntax issue actually
    // requires that ambiguity between function declarations and function
    // expressions be eliminated, which can be done by wrapping the function
    // expression in parens.
    
    // The following pattern is used universally to create an anonymous
    // closure with "privacy":
    
    (function(){ /* code goes here */ })();
    
    // This parens syntax is also valid (I prefer the previous version):
    
    (function(){ /* code goes here */ }());
    

    最后那部分让我印象深刻。有人能解释为什么有两种不同的语法版本来调用函数表达式吗?

    有意识地引入这种语法仅仅是为了调用匿名闭包吗?还是其他句法属性的副产品?

    为什么第二个版本仍然有效?第一个对我来说从解析器的角度来说是有意义的。第一对parens求值为函数对象,第二对调用此函数对象。但是第二个呢?它看起来不像是在解决前面提到的语法歧义。

    有人能告诉我这里缺了什么吗?

    2 回复  |  直到 14 年前
        1
  •  3
  •   Victor Nicollet    14 年前

    所有这些都是因为JavaScript有两个解析上下文:表达式和语句。写作 function foo() {} 在语句级定义函数 foo 在这个范围内 函数foo(){} 在表达式级别计算为一个新的匿名函数(它可以递归地调用自己为 ).

    因此,每当遇到该构造时,解析器必须确定它是在表达式级还是在语句级。默认情况下,它假定处于语句级别,除非另有说明。括号是一种句法表达方式。” 这是一个表达式 ".

    所以,写作 (function() {}) 使解析器将函数视为表达式。由于表达式只能包含其他表达式(没有语句),因此如果您编写 (something-that-contains function(){} and-other-stuff) 然后函数仍然被当作表达式处理。

        2
  •  1
  •   lijie    14 年前

    第二个是因为括号中的表达式不能解释为函数声明(所以它必须是函数表达式,解决了与原始第一个表达式的歧义问题)。