May function declarations appear inside statements in JavaScript?
请将官方ECMAScript规范视为您答案的来源,而不是特定浏览器供应商发布的文档。(我知道Mozilla使用"函数语句"扩展了其JavaScript实现。)
因此,根据ecmascript规范,其中定义的句法产物ergo,这是有效的吗?
1 2 3 | if (foo) { function x() { return; } } |
更新:我的问题也可以这样表述:语句生成是否包含函数声明生成?
结论:答案是否定的。
我不同意其他说它是有效的答案。
根据ECMA-262第5版规范,
1 2 3 4 5 6 | Block : { StatementList opt } StatementList : Statement StatementList Statement |
但是,规范没有定义函数语句,只定义了一个
Several widely used implementations of ECMAScript are known to support the use of
FunctionDeclaration as aStatement . However there are significant and irreconcilable variations among the implementations in the semantics applied to suchFunctionDeclarations . Because of these irreconcilable difference, the use of aFunctionDeclaration as aStatement results in code that is not reliably portable among implementations. It is recommended that ECMAScript implementations either disallow this usage ofFunctionDeclaration or issue a warning when such a usage is encountered. Future editions of ECMAScript may define alternative portable means for declaring functions in aStatement 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, aFunctionDeclaration is not aStatement ; there are places in a program where aStatement is permitted but aFunctionDeclaration 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, evaluateFze upon entering the execution context that it appears in. Yet others, notably DMDScript and default configuration of BESEN, throw aSyntaxError .For consistent behavior across implementations, do not use function statement; use either
FunctionExpression orFunctionDeclaration 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
语法中没有允许
只允许函数表达式是语句的一部分:
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 SemanticsThe 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