请考虑将官方 ECMAScript 规范作为您的答案的来源,而不是由特定浏览器供应商发布的文档。(我知道 Mozilla 使用“函数语句”扩展其 JavaScript 实现。)
那么,根据 ECMAScript 规范,ergo,其中定义的句法产生式,这是有效的吗?
if (foo) {
function x() { return; }
}
更新:我的问题也可以这样表述: Statement生成式是否包含FunctionDeclaration生成式?
结论:答案是否定的。
请考虑将官方 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
然而,规范没有定义函数语句,而只定义了 aFunctionDeclaration
和 a FunctionExpression
。规范进一步在第 12 节中对此进行了说明:
众所周知,ECMAScript 的几个广泛使用的实现支持使用
FunctionDeclaration
作为Statement
. 然而,在应用于此类的语义的实现之间存在显着且不可调和的变化FunctionDeclarations
。由于这些不可调和的差异,使用 aFunctionDeclaration
作为Statement
结果会导致代码在实现之间不能可靠地移植。建议 ECMAScript 实现要么禁止这种用法,FunctionDeclaration
要么在遇到这种用法时发出警告。ECMAScript 的未来版本可能会定义替代的可移植方式来在Statement
上下文中声明函数。
如需进一步阅读,您可能还有兴趣查看comp.lang.javascript FAQ Section 4.2:
4.2 什么是函数语句?
术语函数语句已被广泛且错误地用于描述
FunctionDeclaration
. 这是一种误导,因为在 ECMAScript 中,aFunctionDeclaration
不是Statement
; 程序中有些地方Statement
允许 a 但不允许 aFunctionDeclaration
。为了增加这种混淆,一些实现,特别是 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}
我不知道如何阅读这篇文章,但ECMA-262 V5有这样的说法:
注意 众所周知,ECMAScript 的几个广泛使用的实现支持
FunctionDeclaration
作为语句的使用。然而,在应用于此类 FunctionDeclarations 的语义的实现之间存在显着且不可调和的变化。由于这些不可调和的差异,使用 FunctionDeclaration 作为 Statement 会导致代码在实现之间不能可靠地移植。建议 ECMAScript 实现要么禁止 FunctionDeclaration 的这种用法,要么在遇到这种用法时发出警告。ECMAScript 的未来版本可能会定义替代的可移植方式,用于在 Statement 上下文中声明函数。
如果我理解正确,严格来说,这意味着函数声明根本不能在块内,因为块只能包含语句。
不过,我的解释可能完全错误 - 我不熟悉 ECMAScript 的内部工作原理。
不,它是无效的。函数声明只能作为“源元素”出现,它们要么在全局范围内,要么直接在另一个函数定义中,在所有其他语句之外。来自 ECMA-262 规范:
函数体:源元素
程序:SourceElements
SourceElement : 声明 | 函数声明
语法中没有其他产生式允许FunctionDeclaration
.
只允许函数表达式作为语句的一部分:
MemberExpression : 函数表达式
...
语句:表达式语句
编辑:最近对另一个问题进行了相关讨论。请参阅对此答案的评论- 早些时候,我也认为这可能是有效的,但语法明确表明它是无效的。
- 程序语法
程序: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。
如果 Result(1) 是突然完成,则返回 Result(1)
评估 SourceElement。
返回结果(3)。
生产 SourceElement : *语句通过不采取任何行动来处理函数* 声明。
生产 SourceElement : *语句评估如下: *
1. 评估声明。
2. 返回结果(1)。
为函数声明处理生产 SourceElement : FunctionDeclaration 如下:
- Process FunctionDeclaration 用于函数声明(见第 13 节)。
生产 SourceElement : FunctionDeclaration 的评估如下:
- 返回(正常,空,空)。
awnser 正式为 NO。(Šime Vidas 在另一个问题中艰难地说服了我)
但是没有指定异常,因此它会失败或静默工作,具体取决于浏览器的实现。
ECMA-262 的第 5 版说它不应该是有效的:
FunctionDeclarations 只允许出现在 Program 或 FunctionBody 中。在语法上,它们不能出现在 Block ({ ... }) 中——例如 if、while 或 for 语句。这是因为 Blocks 只能包含 Statements,而不能包含 FunctionDeclaration 的 SourceElements。如果我们仔细查看产生式规则,我们可以看到在 Block 中允许 Expression 的唯一方式是当它是 ExpressionStatement 的一部分时。但是,ExpressionStatement 被明确定义为不以“function”关键字开头,这正是使 FunctionExpression 作为 Statement 或 Block 的一部分无效的原因(请注意,Block 只是 Statements 的列表)。
然而,似乎没有多少口译员遵守这个规则。Kangax 说他们应该被认为是这个页面的语法错误:
由于这些限制,无论何时函数出现在块中(例如在前面的示例中),它实际上都应该被视为语法错误,而不是函数声明或表达式。问题是我见过的几乎没有一个实现严格按照规则解析这些函数(BESEN 和 DMDScript 除外)。相反,他们以专有的方式解释它们。