【问题标题】:Why are there two different syntaxes for invoking anonymous function expressions?为什么调用匿名函数表达式有两种不同的语法?
【发布时间】:2010-11-28 15:47:09
【问题描述】:

我刚刚在Immediately-Invoked Function Expressions 上阅读了Ben Alman 的文章并想知道这部分,他在其中介绍了函数表达式和闭包(还没有真正与IIFE 相关):

// ...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 */ }());

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

是否有意引入这种语法只是为了调用匿名闭包?还是它是其他语法属性的副产品?

为什么第二个版本仍然有效?从解析器的角度来看,第一个对我来说很有意义。第一对括号计算为一个函数对象,第二对调用这个函数对象。但是第二个呢?看起来它并没有解决上面提到的语法歧义。

谁能告诉我这里缺少什么?

【问题讨论】:

    标签: javascript syntax closures


    【解决方案1】:

    这一切都是因为 JavaScript 有两个解析上下文:表达式和语句。在语句级别写入function foo() {} 定义了该范围内的函数foo,而在表达式级别写入function foo() {} 计算为一个新的匿名函数(可以递归调用自身为foo)。

    因此,无论何时遇到该构造,解析器都必须确定它是在表达式级别还是语句级别。默认情况下,它假定处于语句级别,除非另有说服力。括号是表示“这是一个表达式”的语法方式。

    因此,写入(function() {}) 会使解析器将函数视为表达式。由于表达式只能包含其他表达式(不能包含语句),所以如果你写(something-that-contains function(){} and-other-stuff),那么里面的函数仍然会被视为一个表达式。

    【讨论】:

    • 优秀的答案。正是我一直在寻找的东西(但想不出我自己)。 :) 谢谢!
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-14
      • 2020-11-22
      • 1970-01-01
      • 2018-01-02
      • 2012-05-11
      • 1970-01-01
      • 2010-11-11
      相关资源
      最近更新 更多