函数声明可以出现在javascript中的语句中吗?

May function declarations appear inside statements in JavaScript?

请将官方ECMAScript规范视为您答案的来源,而不是特定浏览器供应商发布的文档。(我知道Mozilla使用"函数语句"扩展了其JavaScript实现。)

因此,根据ecmascript规范,其中定义的句法产物ergo,这是有效的吗?

1
2
3
if (foo) {
    function x() { return; }
}

更新:我的问题也可以这样表述:语句生成是否包含函数声明生成?

结论:答案是否定的。


我不同意其他说它是有效的答案。

根据ECMA-262第5版规范,Blocks只能包含Statements(第12.1节):

1
2
3
4
5
6
Block :
   { StatementList opt }

StatementList :
   Statement
   StatementList  Statement

但是,规范没有定义函数语句,只定义了一个FunctionDeclaration和一个FunctionExpression。规范在第12节进一步说明了这一点:

Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations. Because of these irreconcilable difference, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations. It is recommended that ECMAScript implementations either disallow this usage of FunctionDeclaration or issue a warning when such a usage is encountered. Future editions of ECMAScript may define alternative portable means for declaring functions in a Statement context.

为了进一步阅读,您还可能有兴趣查看comp.lang.javascript常见问题解答第4.2节:

4.2 What is a function statement?

The term function statement has been widely and wrongly used to describe a FunctionDeclaration. This is misleading because in ECMAScript, a FunctionDeclaration is not a Statement; there are places in a program where a Statement is permitted but a FunctionDeclaration is not. To add to this confusion, some implementations, notably Mozillas', provide a syntax extension called function statement. This is allowed under section 16 of ECMA-262, Editions 3 and 5.

Example of nonstandard function statement:

1
2
3
4
5
6
// Nonstandard syntax, found in GMail source code. DO NOT USE.
try {
  // FunctionDeclaration not allowed in Block.
  function Fze(b,a){return b.unselectable=a}
  /*...*/
} catch(e) { _DumpException(e) }

Code that uses function statement has three known interpretations. Some implementations process Fze as a Statement, in order. Others, including JScript, evaluate Fze upon entering the execution context that it appears in. Yet others, notably DMDScript and default configuration of BESEN, throw a SyntaxError.

For consistent behavior across implementations, do not use function statement; use either FunctionExpression or FunctionDeclaration instead.

Example of FunctionExpression (valid):

1
2
3
4
5
var Fze;
try {
  Fze = function(b,a){return b.unselectable=a};
  /*...*/
} catch(e) { _DumpException(e) }

Example of FunctionDeclaration (valid):

1
2
// Program code
function aa(b,a){return b.unselectable=a}


不,它是无效的。函数声明只能以"源元素"的形式出现,这些元素要么在全局范围内,要么直接在另一个函数定义内,在所有其他语句之外。根据ECMA-262规范:

FunctionBody : SourceElements

Program : SourceElements

SourceElement : Statement | FunctionDeclaration

语法中没有允许FunctionDeclaration的其他生成。

只允许函数表达式是语句的一部分:

MemberExpression : FunctionExpression

...

Statement : ExpressionStatement

编辑:最近有一个关于另一个问题的相关讨论。看看关于这个答案的评论-早些时候,我也认为这可能是有效的,但是语法清楚地表明它是无效的。


我不知道怎么读这个,但是ECMA-262 v5有个说法:

NOTE Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations. Because of these irreconcilable difference, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations. It is recommended that ECMAScript implementations either disallow this usage of FunctionDeclaration or issue a warning when such a usage is encountered. Future editions of ECMAScript may define alternative portable means for declaring functions in a Statement context.

严格地说,如果我正确理解这一点,这意味着函数声明根本不能在块内,因为块只能包含语句。

不过,我的解释可能完全错了——我不熟悉ecmascript的内部工作原理。


摘自ECMA 262第14章

  • Program Syntax
  • Program : SourceElements
    SourceElements : SourceElement
    SourceElements SourceElement
    SourceElement : Statement
    FunctionDeclaration Semantics

    The production Program :
    SourceElements is evaluated as
    follows:

  • Process SourceElements for function declarations.

  • Evaluate SourceElements.

  • Return Result(2).

  • The production SourceElements :
    SourceElement is processed for
    function declarations as follows:

  • Process SourceElement for function declarations.
  • The production SourceElements :
    SourceElement is evaluated as follows:

  • Evaluate SourceElement.

  • Return Result(1).

  • The production SourceElements :
    SourceElements SourceElement is
    processed for function declarations as
    follows:

  • Process SourceElements for function declarations.

  • Process SourceElement for function declarations.

  • The production SourceElements :
    SourceElements SourceElement is
    evaluated as follows:

  • Evaluate SourceElements.

  • If Result(1) is an abrupt completion, return Result(1)

  • Evaluate SourceElement.

  • Return Result(3).

  • The production SourceElement :
    *Statement is processed for function*
    declarations by taking no action.

    The production SourceElement :
    *Statement is evaluated as follows:*

    1. Evaluate Statement.

    2. Return Result(1).

    The production SourceElement :
    FunctionDeclaration is processed for
    function declarations as follows:

  • Process FunctionDeclaration for function declarations (see clause 13).
  • The production SourceElement :
    FunctionDeclaration is evaluated as
    follows:

  • Return (normal, empty, empty).
  • 雨篷是官方编号。IME VIDAS用另一个问题说服了我。)

    但也没有指定异常,因此它会失败,或者根据浏览器实现自动工作。


    ECMA-262的第5版说它不应该是有效的:

    FunctionDeclarations are only allowed
    to appear in Program or FunctionBody.
    Syntactically, they can not appear in
    Block ({ ... }) — such as that of if,
    while or for statements. This is
    because Blocks can only contain
    Statements, not SourceElements, which
    FunctionDeclaration is. If we look at
    production rules carefully, we can see
    that the only way Expression is
    allowed within Block is when it is
    part of ExpressionStatement. However,
    ExpressionStatement is explicitly
    defined to not begin with"function"
    keyword, and this is exactly what
    makes FunctionExpression invalid as
    part of a Statement or Block (note
    that Block is merely a list of
    Statements).

    然而,似乎没有多少口译员遵守这条规则。Kangax说,每页都应该考虑语法错误:

    Because of these restrictions,
    whenever function appears in a block
    (such as in previous example) it
    should actually be considered a syntax
    error, not function declaration or
    expression. The problem is that almost
    none of the implementations I've seen
    parse these functions strictly per
    rules (exceptions are BESEN and
    DMDScript). They interpret them in
    proprietary ways instead.


    在EcmaScript标准中,函数声明不定义为语句,语句也不定义为能够包含函数声明,因此根据标准,它们不兼容(尽管在实践中,每个javascript解释器都会尝试做一些明智的事情,尽管实现之间不一致)。


    是的,它是有效的。

    所有语句块(即大括号内的所有内容)都可以有附加的语句和声明,包括函数。

    因此,您还可以在函数中定义函数,等等

    以下是ECMA-262 v1-http://www.mozilla.org/js/language/e262.pdf