Labeled functon语句-未定义的标签



我查看了规范,不明白为什么这段代码会导致错误:

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

在使用代码块的同时,它运行良好:

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

顺便说一句,我可以逐个标记函数,而不用在函数内部使用那个标签。我不会得到错误:

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

主要问题:如果我们不能在函数内部使用标签,那么标签函数语句的主要目的是什么?

TLDR

到20世纪90年代中期,CCD_;危险的";令人困惑,因此被排除在新语言之外。但突然退出或";跳跃;块外构造(块、try、with、if、loop构造)仍然是一个理想的特性,因此标签和break/continue被包括在内,作为一种淡化的替换。

请注意,标签和break/continue无法启用更强大的goto的循环行为:它们只允许您有效地向前跳出块。

函数也是类似块的构造。根据规范,函数不是语句,因此不能标记,但在网络的早期,标准被视为仅仅是灵活的指导方针;因此,浏览器供应商不一致地启用了函数的标记("标记的函数语句")[这将为return提供一种替代语法?]这种行为不在原始标准中,但在ES2015中进行了向后标准化,以便在break <label>/continue <label>引用了标记的函数声明时抛出错误,尽管出于向后兼容性的原因,不引用标签的带标签的函数语句将被允许。

这解释了你观察到的行为。

详细信息

根据规范,您可以用JavaScript标记所有语句。自从ECMAScript 2.0版本以来,这种情况一直存在,当时标签被添加到该语言中。

以下是JS中的语句类型:

BlockStatement,VariableStatement,EmptyStatement,ExpressionStatement、IfStatement、BreakableStatement、,ContinueStatement,BreakStatement,ReturnStatement,WithStatement,Labeled语句、ThrowStatement、TryStatement、Debugger语句。

请注意,块是语句。

但是标签只能用于goto0和continue,因此在允许的情况下标记其中一些语句(例如,Variable、Return、Throw)是毫无意义的。

这意味着标签可以应用于不能使用breakcontinue的结构,使这些位置的标签实际上只能用作伪注释。

该语言是这样设计的,因为它通过避免对";死标签分析";。

"函数语句";是函数";在语句位置";。ECMAScript 5.1有以下内容:

ECMAScript的几个广泛使用的实现已知支持将FunctionDeclaration用作语句。然而,在应用于此类FunctionDeclarations的语义中,实现之间存在显著且不可调和的差异。由于这些不可调和的差异,将FunctionDeclaration用作语句会导致代码在实现之间无法可靠地移植。建议ECMAScript实现不允许使用FunctionDeclaration,或者在遇到这种使用时发出警告。ECMAScript的未来版本可能会定义在Statement上下文中声明函数的可移植方法。

这意味着在一些较旧的浏览器中;声明";有时可以被视为一种陈述,因此它们可以被贴上标签。我不知道历史浏览器的标签功能的确切行为是什么。如果您试图引用标签,现代浏览器会引发语法错误,正如您所发现的那样。

因此以下(try语句)是有效的JS:

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

并且以下(switch语句)有效:

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

但是,以下(return语句)也是有效的(但毫无意义):

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

这个变量语句的标签也毫无意义:

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

最新更新