2012-07-17 7 views
8

Estaba navegando a la source of JSLint y notamos este pedazo de código:¿Qué hay de malo con el uso de una declaración etiquetada en el código global?

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

La parte interesante es la comparación funct === global_funct. Ejecutar el siguiente fragmento través JSLint lanza una "etiqueta inesperado" error, ya que la declaración de la etiqueta está en el contexto de ejecución mundial (lo sé, es un ejemplo estúpida Here's a fiddle..):

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

Si se coloca el mismo fragmento en una función, JSLint está perfectamente satisfecho con eso y no arroja un error cuando encuentra la etiqueta. Here's a fiddle con el código que pasará JSLint. El código se puede pegar en el online version of JSLint si quieres probarlo.

Así que mi pregunta: ¿hay algo de malo con el uso de una declaración etiquetada en el código global o es simplemente otra opción personal de Crockford?

+0

se ve sospechosamente como una variación de "Goto considera perjudicial." –

+0

Realmente espero que esto no es compatible con JavaScript moderna: https://developer.mozilla.org/en/JavaScript/Reference/Statements/label – jbabey

+0

@RobertHarvey - Lo hace en efecto, pero ¿por qué se comportan de manera diferente en código global? –

Respuesta

3

Después de una investigación sobre el comportamiento de las declaraciones etiquetadas, creo que en realidad es solo una elección de Crockford sin ninguna base real de hecho. Por lo que puedo decir, no hay ninguna situación que pueda causar un conflicto de nombres con las etiquetas en el alcance global (y esa parece ser la razón principal por la que las personas pueden pensar por qué JSLint no lo permite - ver comentarios sobre la pregunta).

Los estados de especificaciones ES5 lo siguiente en el section on labelled statements:

La producción Identificador: Declaración de se evalúa mediante la adición de Identificador al conjunto de etiqueta de Declaración y luego evaluar Declaración.

...

Antes de la evaluación de un LabelledStatement , el contenido Declaración es considerada como poseedora de un conjunto etiqueta vacía, salvo que sea una IterationStatement o un SwitchStatement , en el cual caso se considera que posee un conjunto de etiquetas que consiste en el elemento único, empty.

Tomo esto para significar que cada declaración tiene un conjunto de etiquetas. Los identificadores de etiqueta son independientes de los identificadores de variables y funciones, por lo que es sintácticamente aceptable tener una etiqueta con el mismo identificador que una variable en el mismo ámbito.En otras palabras, esto es válido:

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

Dado que cada sentencia tiene su propio conjunto de etiquetas, esto también es válido:

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; 
} 

Ya que se puede etiquetar cualquier declaración (que no tiene sentido, pero es posible) , puede etiquetar una sentencia etiquetada:

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

Cuando este es el caso, los estados de especificaciones lo siguiente:

Si el LabelledStatement tiene un conjunto de etiquetas no vacías, estas etiquetas también se agregan al conjunto de etiquetas de Statement antes de evaluarlo.

En el fragmento anterior, el conjunto de etiquetas de la declaración for contiene dos etiquetas (another y label). Es posible romper a ya sea de esas etiquetas dentro de la sentencia for.

Y, por último, la especificación también establece (énfasis añadido):

declaraciones marcados se utilizan sólo en combinación con la etiqueta break y continue declaraciones. ECMAScript no tiene goto declaración.

En base a todo eso, no puedo pensar en una posible forma de que las etiquetas en el código global interfieran con otros códigos globales. Por supuesto, es muy poco probable que desee un programa que contenga varias etiquetas con el mismo identificador, y JSLint ya lo previene arrojando un error de "etiqueta ya está definida". Pero no creo que haya ninguna diferencia con la forma en que trata las declaraciones etiquetadas en el contexto de ejecución global.

Cuestiones relacionadas