2010-11-28 66 views
1

我刚阅读Immediately-Invoked Function ExpressionsBen Alman的文章,并想知道这个部分,在那里他介绍函数表达式和闭包(没有真正涉及到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求值为一个函数对象,第二对调用该函数对象。但第二个?它看起来不像是解决了所提到的句法歧义。

有人可以告诉我我在这里失踪了吗?

回答

3

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

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

因此,编写(function() {})会导致解析器将该函数视为表达式。由于表达式只能包含其他表达式(无语句),因此如果您编写(something-that-contains function(){} and-other-stuff),则其中的函数仍将被视为表达式。

+0

优秀的答案。正是我在寻找的东西(但想不起自己)。 :) 谢谢! – 2010-12-04 17:35:50

1

第二个工作原理是因为括号中的表达式不能被解释为函数声明(所以它必须是一个函数表达式,用原始第一个表达式解决含糊问题)。

相关问题