简体   繁体   English

标记的函数语句 - 未定义 label

[英]Labelled functon statement - Undefined label

I look at spec and I can't understand why this code cause an error:我查看了规范,但不明白为什么这段代码会导致错误:

L: function a(){
  console.log(1);
  break L; /// Uncaught SyntaxError: Undefined label 'L'
  console.log(2);
}

a(); 

In the same time with code blocks it works well:同时与代码块一起运行良好:

M: {
  console.log(1);
  break M;
  console.log(2)
}

By the way I can just mark function by label without using that label inside function. And I won't get an error:顺便说一句,我可以用 label 标记 function,而无需在 function 中使用 label。而且我不会收到错误消息:

L: function a(){
  console.log(1);
  console.log(2);
}

a(); 

Main question: What is the main purpose of labelled function statements if we can't use label inside function?主要问题:如果我们不能在 function 中使用 label,那么标记为 function 的语句的主要目的是什么?

TLDR TLDR

By the mid-1990s goto was frowned-upon as being "dangerous" and confusing and was thus elided from new languages.到 20 世纪 90 年代中期, goto因“危险”和令人困惑而不受欢迎,因此被从新语言中删除。 But abruptly exiting or "jumping" out of block constructs (blocks, try, with, if, loop constructs) was still a desirable feature, and so labels and break / continue were included as a kind of watered-down replacement.但是突然退出或“跳出”块结构(块、try、with、if、循环结构)仍然是一个理想的特性,因此标签和break / continue被包括为一种淡化的替代品。

Note how labels and break / continue do not enable the looping behavior of the more powerful goto : they only allow you to effectively jump forward, out of a block.请注意标签和break / continue如何不启用更强大的goto的循环行为:它们只允许您有效地向前跳出块。

Functions are also block-like constructs.函数也是类似块的结构。 According to the spec, functions were not statements and therefore could not be labelled, but standards were seen as mere flexible guidelines during the early years of the Web;根据规范,功能不是陈述,因此不能被标记,但在 Web 的早期,标准被视为仅仅是灵活的指导方针; thus browser vendors inconsistently enabled the labelling of functions ("labelled function statements") [which would provide an alternative syntax to return ?] This behavior was not in the original standard, but was backwards-standardized in ES2015 to throw an error if a labelled function statement was referenced by break <label> / continue <label> , although a labelled function statement without a reference to the label would be allowed for backwards compatibility reasons.因此浏览器供应商不一致地启用函数标签(“标签为 function 语句”)[这将提供替代语法来return ?] 这种行为不在原始标准中,但在 ES2015 中被向后标准化以在标签为function 语句被break <label> / continue <label>引用,尽管出于向后兼容性的原因,允许不引用 label 的标记为 function 的语句。

This explains the behavior you observe.这解释了您观察到的行为。

Details细节

According to the spec, you can label all statements in JavaScript .根据规范,您可以 label 中的所有语句 JavaScript This has been so since ECMAScript version 2.0 , when labels were added to the language.ECMAScript 2.0 版以来一直如此,当时语言中添加了标签。

These are the kinds of statement in JS: 这些是JS中的语句类型:

BlockStatement, VariableStatement, EmptyStatement, ExpressionStatement, IfStatement, BreakableStatement, ContinueStatement, BreakStatement, ReturnStatement, WithStatement, LabelledStatement, ThrowStatement, TryStatement, DebuggerStatement. BlockStatement、VariableStatement、EmptyStatement、ExpressionStatement、IfStatement、BreakableStatement、ContinueStatement、BreakStatement、ReturnStatement、WithStatement、LabelledStatement、ThrowStatement、TryStatement、DebuggerStatement。

Note that blocks are statements.请注意,块是语句。

But labels are only useable with break and continue , and so labelling some of these statements (eg. Variable, Return, Throw), while permitted, is pointless.但是标签只能与breakcontinue一起使用,因此在允许的情况下标记其中一些语句(例如 Variable、Return、Throw)是没有意义的。

This means that labels can be applied to constructs with which break and continue cannot be used, making labels in those positions de facto only useable as pseudo-comments.这意味着标签可以应用于不能使用breakcontinue的结构,使这些位置的标签实际上只能用作伪注释。

The language was designed this way because it simplified engine development by avoiding the need for "dead label analysis" .这种语言是这样设计的,因为它通过避免“死 label 分析”的需要简化了引擎开发

"Function statements" were functions "in the statement position". “函数语句”是“在语句位置”的函数。 ECMAScript 5.1 had the following to say: ECMAScript 5.1 有以下内容:

Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement.众所周知,几种广泛使用的 ECMAScript 实现支持将 FunctionDeclaration 用作语句。 However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations.然而,在应用于此类 FunctionDeclarations 的语义的实现之间存在显着且不可调和的变化。 Because of these irreconcilable differences, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations.由于这些不可调和的差异,将 FunctionDeclaration 用作 Statement 会导致代码无法在实现之间可靠地移植。 It is recommended that ECMAScript implementations either disallow this usage of FunctionDeclaration or issue a warning when such a usage is encountered.建议 ECMAScript 实现要么禁止 FunctionDeclaration 的这种用法,要么在遇到这种用法时发出警告。 Future editions of ECMAScript may define alternative portable means for declaring functions in a Statement context. ECMAScript 的未来版本可能会定义替代的可移植方法,用于在语句上下文中声明函数。

This means that in some older browsers function "declarations" could sometimes be treated as a statement, and therefore they could be labelled.这意味着在某些较旧的浏览器中 function “声明”有时可以被视为声明,因此可以对其进行标记。 What the precise behavior of historical browsers was with labelled functions I do not know.我不知道历史浏览器对标记函数的准确行为是什么。 Modern browsers raise a syntax error if you attempt to refer to the label, as you found.如果您尝试引用 label,现代浏览器会引发语法错误,如您所见。

So the following (a try statement) is valid JS:所以下面的(一个try语句)是有效的 JS:

 let foo = 'a' myLabel: try { if(foo === 'a') break myLabel console.log('this will not be printed') } catch {} console.log('all done')

...and the following ( switch statement) is valid: ...并且以下( switch语句)是有效的:

 let foo = 'a' myLabel: switch(foo) { case 'a': break myLabel console.log('this will not be printed') } console.log('all done.')

But also, the following ( return statement) is valid (but pointless):而且,以下( return语句)是有效的(但毫无意义):

 function foo() { myLabel: return 'result of foo' } console.log(foo())

...and the labelling of this variable statement is pointless too: ...并且此变量语句的标签也毫无意义:

 myLabel: var foo = 'value of foo' console.log('works fine, but the label was pointless')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM