请将官方ECMAScript规范视为您的答案来源,而不是特定浏览器供应商发布的文档。 (我知道Mozilla用“函数语句”扩展了它的JavaScript实现。)
那么,根据ECMAScript规范,ergo,其中定义的句法产品,是否有效?
if (foo) {
function x() { return; }
}
更新: 我的问题也可以这样说: Statement 生产是否包含 FunctionDeclaration 生产?
结论: 答案是否定的。
答案 0 :(得分:20)
我不同意其他有效的答案。
根据ECMA-262 5th Edition specification,Blocks
只能包含Statements
(Section 12.1):
Block :
{ StatementList opt }
StatementList :
Statement
StatementList Statement
但是规范没有定义函数语句,只有FunctionDeclaration
和FunctionExpression
。该规范进一步在Section 12中对此进行了说明:
已知几种广泛使用的ECMAScript实现支持将
FunctionDeclaration
用作Statement
。然而,在应用于此类FunctionDeclarations
的语义中的实现之间存在显着且不可调和的变化。由于这些不可调和的差异,使用FunctionDeclaration
作为Statement
会导致代码在实现中无法可靠地移植。建议ECMAScript实现不允许使用FunctionDeclaration
或在遇到此类用法时发出警告。 ECMAScript的未来版本可以定义用于在Statement
上下文中声明函数的替代可移植方法。
如需进一步阅读,您可能还有兴趣查看comp.lang.javascript FAQ Section 4.2:
4.2什么是函数语句?
术语函数语句被广泛而错误地用于描述
FunctionDeclaration
。这是误导性的,因为在ECMAScript中,FunctionDeclaration
不是Statement
;程序中有些地方允许Statement
但FunctionDeclaration
不允许。为了增加这种混淆,一些实现,特别是Mozillas',提供了一种称为函数语句的语法扩展。 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
。对于跨实现的一致行为,不要使用函数语句;请改用
FunctionExpression
或FunctionDeclaration
。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}
答案 1 :(得分:3)
我不知道如何阅读本文,但ECMA-262 V5有这样的说法:
注意已知几种广泛使用的ECMAScript实现支持使用
FunctionDeclaration
作为语句。然而,在应用于此类FunctionDeclarations的语义中的实现之间存在显着且不可调和的变化。由于这些不可调和的差异,使用FunctionDeclaration作为Statement会导致代码在实现中无法可靠地移植。建议ECMAScript实现不允许使用FunctionDeclaration,或在遇到此类用法时发出警告。 ECMAScript的未来版本可以定义用于在Statement上下文中声明函数的替代可移植方法。
如果我理解正确,严格来说,这意味着函数声明根本不能在块内,因为块只能包含语句。
我的解释可能完全错误 - 但我不熟悉ECMAScript的内部工作原理。
答案 2 :(得分:3)
不,它无效。函数声明只能作为“源元素”出现,它们位于全局范围内,或者在另一个函数定义中,在所有其他语句之外。来自ECMA-262规范:
FunctionBody:SourceElements
计划:SourceElements
SourceElement:Statement | FunctionDeclaration
语法中没有其他产品允许FunctionDeclaration
。
只允许函数表达式成为语句的一部分:
MemberExpression:FunctionExpression
...
声明:ExpressionStatement
编辑:最近有关于另一个问题的相关讨论。请参阅this answer上的评论 - 之前,我也认为此可以有效,但语法清楚表明它无效。
答案 3 :(得分:2)
- 程序语法
醇>计划:SourceElements SourceElements:SourceElement SourceElements SourceElement SourceElement:Statement FunctionDeclaration Semantics
制作计划: SourceElements评估为 如下:
处理函数声明的SourceElements。
评估SourceElements。
- 醇>
返回结果(2)。
生产SourceElements: 处理SourceElement 函数声明如下:
- 处理函数声明的SourceElement。
醇>生产SourceElements: SourceElement的评估如下:
评估SourceElement。
- 醇>
返回结果(1)。
生产SourceElements: SourceElements SourceElement是 处理函数声明为 如下:
处理函数声明的SourceElements。
- 醇>
处理函数声明的SourceElement。
生产SourceElements: SourceElements SourceElement是 评估如下:
评估SourceElements。
如果结果(1)突然完成,则返回结果(1)
评估SourceElement。
- 醇>
返回结果(3)。
制作SourceElement: * 语句处理功能 * 声明,不采取任何行动。
制作SourceElement: * 声明评估如下: *
<强> 1。评估声明。
<强> 2。返回结果(1)。
生产SourceElement: 处理FunctionDeclaration 函数声明如下:
- 函数声明的Process FunctionDeclaration(见第13节)。
醇>生产SourceElement: FunctionDeclaration评估为 如下:
- 返回(正常,空,空)。
醇>
芒果正式没有。 (ŠimeVidas在另一个问题上让我很难相信)
但是没有指定Exception,因此根据浏览器的实现,它会失败或无声地工作。
答案 4 :(得分:1)
ECMA-262的第5版说它不应该有效:
仅允许使用FunctionDeclarations 出现在Program或FunctionBody中。 从语法上讲,它们不能出现在 阻止({...}) - 如if, 而对于陈述。这是 因为块只能包含 声明,而不是SourceElements,其中 FunctionDeclaration是。如果我们看一下 仔细制作规则,我们可以看到 这是Expression的唯一方式 Block内允许的时间是 ExpressionStatement的一部分。然而, ExpressionStatement是显式的 定义为不以“功能”开头 关键字,这正是如此 使FunctionExpression无效为 声明或块的一部分(注意 那个Block只是一个列表 语句)。
但是,似乎没有多少口译员遵守这一规则。 Kangax说他们应该被视为每this page的语法错误:
由于这些限制, 每当函数出现在块中时 (例如在前面的例子中)它 应该被认为是一种语法 错误,不是函数声明或 表达。问题是差不多 没有我见过的任何实现 严格解析这些功能 规则(例外是BESEN和 DMDScript)。他们解释他们 专有的方式。
答案 5 :(得分:0)
在ECMAScript标准中,FunctionDeclaration未定义为Statement,并且Statement未定义为能够包含FunctionDeclaration,因此它们根据标准不兼容(尽管实际上每个JavaScript解释器都会尝试做某事是明智的,尽管实现之间并不一致。)
答案 6 :(得分:-1)
是的,它是有效的。
所有语句块(即花括号内的所有内容)都可以包含其他语句和声明,包括函数。
所以你也可以在函数中定义函数等等
这是ECMA-262 v1 - http://www.mozilla.org/js/language/E262.pdf