可能函数声明出现在JavaScript语句中?

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

因此,根据ECMAScript规范,ergo,其中定义的语法生成是否有效?

if (foo) {
    function x() { return; }
}

更新:我的问题也可以这样表述:Statement生产包含FunctionDeclaration生产吗?

结论:答案是否定的。


我不同意其他答案,认为它是有效的。

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

Block :
   { StatementList opt }

StatementList :
   Statement
   StatementList  Statement

然而,规范没有定义一个函数声明,但只是一个FunctionDeclarationFunctionExpression 。 规范进一步在第12节中对此进行了说明:

已知几种广泛使用的ECMAScript实现支持将FunctionDeclaration用作Statement 。 然而,在应用于这些FunctionDeclarations的语义中,这些实现之间存在重大且不可调和的变化。 由于这些不可调和的差异,使用FunctionDeclaration作为Statement导致代码在实现中不可靠。 建议ECMAScript实现要么不允许使用FunctionDeclaration要么在遇到这种用法时发出警告。 ECMAScript的未来版本可以定义用于在Statement上下文中声明函数的可选便携式方法。

如需进一步阅读,您可能还有兴趣查看comp.lang.javascript常见问题解答部分4.2:

4.2什么是函数声明?

术语函数声明被广泛地错误地用于描述FunctionDeclaration 。 这是误导性的,因为在ECMAScript中, FunctionDeclaration不是一个Statement ; 程序中有一些地方允许Statement ,但FunctionDeclaration Statement不允许。 为了增加这种混淆,一些实现,特别是Mozilla's,提供了一个名为function statement的语法扩展。 ECMA-262第3版和第5版第16节允许这样做。

非标准函数声明的例子:

// 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) }

使用函数声明的代码有三种已知的解释。 一些实现按顺序处理Fze作为语句。 其他人,包括JScript,在进入它出现的执行上下文时评估Fze 。然而其他人,特别是DMDScript和BESEN的默认配置,会抛出一个SyntaxError

对于跨实现的一致行为,不要使用函数语句; 改用FunctionExpressionFunctionDeclaration

FunctionExpression示例(有效):

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

FunctionDeclaration的示例(有效):

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

我不确定如何阅读,但ECMA-262 V5有这样的说法:

注意已知几种广泛使用的ECMAScript实现支持将FunctionDeclaration用作语句。 然而,在应用于这些函数声明的语义中,这些实现之间存在重大且不可调和的变化。 由于这些不可调和的差异,使用FunctionDeclaration作为语句会导致代码在实现中不可靠。 建议ECMAScript实现要么不允许使用FunctionDeclaration,要么在遇到这种用法时发出警告。 ECMAScript的未来版本可以定义用于在语句上下文中声明函数的可选便携式方法。

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

但我的解释完全错误 - 我不熟悉ECMAScript的内部工作原理。


不,它是无效的。 函数声明只能作为“源元素”出现,它位于全局作用域中或直接位于另一个函数定义中,而不是所有其他语句之外。 从ECMA-262规格:

FunctionBody:SourceElements

程序:SourceElements

SourceElement:Statement | FunctionDeclaration

语法中没有其他生产允许FunctionDeclaration

只有函数表达式才被允许成为声明的一部分:

MemberExpression:FunctionExpression

...

声明:ExpressionStatement

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

链接地址: http://www.djcxy.com/p/17257.html

上一篇: May function declarations appear inside statements in JavaScript?

下一篇: var functionName = function() {} vs function functionName() {}