What is wrong with using a labeled statement in global code?

I was just looking at the JSLint source and noticed this piece of code:

// Is this a labeled statement? //... if (next_token.labeled !== true || funct === global_funct) { stop('unexpected_label_a', label); } //... 

The interesting part is the comparison funct === global_funct . Running the next snippet through JSLint raises an “Unexpected label” error, since the marked statement is in the global execution context (I know this is a dumb example. Here is the fiddle ).

 loop: for (var i = 0; i < 10; i++) { if (i === 5) { break loop; } } 

If you put the same fragment in a function, JSLint fully satisfies it and does not throw an error when a label is detected. Here is the fiddle with the code that JSLint will pass The code can be inserted into the online version of JSLint if you want to try it.

So my question is: is there something wrong with using the tagged statement in the global code, or is it just another personal choice from Crockford?

+8
javascript jslint
source share
1 answer

After some research into the behavior of the labeled statements, I think this is actually just Crockford's choice, with virtually no real basis. As far as I can tell, there is no situation that could cause a conflict of names with labels in the global area (and this, apparently, was the main reason why people could think about why JSLint forbids it) see Comments on the question )

The ES5 specification states the following in the section for tagged instructions :

Product Identifier: Statement is evaluated by adding the Identification Label Set Identifier and then evaluating the Statement.

...

Prior to evaluating a LabelledStatement, the contained expression is considered to have an empty label set if it is not an IterationStatement or SwitchStatement element, in which case it is considered to have a single label set of labels, empty .

I suppose this means that every statement has a set of labels. Label identifiers are independent of variables and function identifiers, so it is syntactically acceptable to have a label with the same identifier as a variable in the same scope. In other words, it really is:

 var label = "My Label"; label: for (var x = 1; x < 10; x++) { break label; } 

Since each operator has its own set of shortcuts, this is also true:

 label: for (var x = 1; x < 10; x++) { //Looks for 'label' in label set of `break` statement, then `for` statement break label; } label: for (var y = 5; y < 15; y++) { //Same again. Will never look for label outside the enclosing `for` statement break label; } 

Since you can mark any statement (it’s pointless, but it’s possible), you can mark the symbol with the inscription:

 another: label: for (var y = 5; y < 15; y++) { break label; } 

If so, the specification states the following:

If the LabelledStatement itself has a non-empty label set, these labels are also added to the Statement label set before evaluating it.

In the above snippet, the label set of the for statement contains two labels ( another and label ). You can break into any of these labels from the for statement.

And finally, the specification also indicates (highlighted by me):

Labeled labels are only used in conjunction with the break and continue caption. ECMAScript does not have goto .

Thus, based on this, I cannot think of a possible way for any labels in global code to interfere with another global code. Of course, it is very unlikely that you will need a program containing several labels with the same identifier, and JSLint already prevents this by choosing the "label is already defined" error. But I don’t think there should be any difference with how it handles labeled statements in the global execution context.

+3
source share

All Articles