2012-07-26 16 views
5

¿Alguien puede explicar por qué el siguiente código js sube dos ventanas de alerta con texto 'string1' en lugar de subir el segundo con texto 'indefinido' adentro ?? Si ambas variables se describen en el mismo alcance ..Variables definidas en alcance global con nombres idénticos

var a = 'string1'; 
alert(a); 
var a; 
alert(a);​ 

http://jsfiddle.net/FdRSZ/1/

Gracias

+0

+1, pregunta interesante. –

+0

Las variables locales también deberían exhibir este mismo comportamiento. – hugomg

Respuesta

6

declaraciones de variables (y declaraciones de funciones) son izada a la parte superior del alcance en el que aparecen. Las asignaciones suceden en el lugar. El código es interpretado de manera efectiva como esto:

var a; 
var a; 
a = 'string1'; 

Por ejemplo, consideremos lo que ocurre si se declara una variable dentro de un cuerpo if declaración:

console.log(myVar); //undefined (NOT a reference error) 
if (something === somethingElse) { 
    var myVar = 10; 
} 
console.log(myVar); //10 

Debido a que JavaScript no tiene ámbito de bloque, todas las declaraciones en cada alcance se eleva a la parte superior de ese alcance. Si intentas registrar alguna variable que no fue declarada, obtendrías un error de referencia. El ejemplo anterior se interpreta así:

var myVar; //Declaration is hoisted 
console.log(myVar); 
if (something === somethingElse) { 
    myVar = 10; //Assignment still happens here 
} 
console.log(myVar); 

Así que incluso si la condición se evalúa false, la variable myVar sigue siendo accesible. Esta es la razón principal por la que JSLint le dirá que mueva todas las declaraciones a la parte superior del alcance en el que aparecen.


En poco más de detalle ... esto es lo que el ECMAScript 5 spec tiene que decir (en negrita cursiva es nuestra):

Para cada VariableDeclaration y VariableDeclarationNoIn d en código, en orden de texto fuente do

  • Deje dn sea el Identificador en d.
  • Vamos varAlreadyDeclared ser el resultado de llamar concreto HasBinding método de env pasar dn como argumento.
  • Si varAlreadyDeclared es false, entonces
    • llamada de env CreateMutableBinding método concreto que pasa dn y configurableBindings como los argumentos.
    • llamada método concreto SetMutableBinding de env pasar dn, undefined, y estricta como los argumentos.

Por lo tanto, si una unión ya existe con el identificador que estamos tratando de unir ahora, no pasa nada.

3

Esto se debe a la segunda var a no es una declaración de la variable independiente. En lo que respecta al intérprete de JavaScript, es el mismo que el primero.

3

var significa "Alcance esta variable para esta función" no "Establezca el valor de esta variable en undefined".

Si la variable ya está en el ámbito de la función a continuación, var foo significa lo mismo que simplemente foo

4

Eso es porque JavaScript hace algo llamado variable de elevación. De hecho, el JS es el siguiente:

var a; // hoisted -> declared on top 

a = 'string1'; 
alert(a); 
alert(a); 

Ver How Good C# Habits can Encourage Bad JavaScript Habits para más detalles sobre el funcionamiento de JavaScript.

+0

Gracias por el enlace, uno útil –

Cuestiones relacionadas