2011-08-26 16 views
5

Como soy un novato en JavaScript, comencé a aprenderlo, pero me quedé atascado solo al principio. Estoy siguiendo a Mozilla Tutorial y tengo un problema con el alcance variable en JavaScript. Tengo un código:Problema con el alcance de la variable

var myvar = "my value"; 

var zmienna = "string"; 

(function() { 
    alert(myvar); 
    alert(zmienna); 
})(); 

(function() { 
    alert(myvar); // undefined 
    var myvar = "local value"; 
    alert(zmienna); 
})(); 

En el tutorial, he leído que las variables de JavaScript no son visibles desde los bloques de funciones. Bueno, las primeras dos alertas dicen valores correctos. Es extraño, porque la tercera alerta dice "indefinido", a pesar de que nada ha cambiado desde el bloque de funciones anterior. El cuarto, una vez más, imprime el valor correcto.

¿Alguien podría explicarme qué pasa aquí? Estaría muy contento, porque el tutorial no dice nada más al respecto.

+0

_ "He leído que las variables JavaScript no son visibles desde bloques de funciones. "_ ¿Dónde está eso en el tutorial? Esa oración simplemente no tiene sentido. –

Respuesta

1

"He leído que las variables de JavaScript no son visibles desde los bloques de funciones."

Eso no es del todo cierto. Están disponibles desde las funciones anidadas.

Las funciones anidadas crean una cadena de alcance . Una función creada dentro de otra función tiene acceso a sus propias variables, así como a las variables de la función en la que fue anidada.

Pero función A puede no ver las variables de función B si la función A no se anida en el interior función B.

var myvar = "my value"; // <-- global variable, seen by all functions  
var zmienna = "string"; // <-- global variable, seen by all functions 

(function() { 
    alert(myvar); // <-- referencing the global variable 
    alert(zmienna); // <-- referencing the global variable 
})(); 
(function() { 
    // v--- Declaration of these "local" variables were hoisted to the top... 
    // var myvar; // <--- ...as though it was here. 
    // var new_var; // <--- ...as though it was here. 

    alert(myvar); // undefined (myvar is delcared, but not initialized) 
    alert(new_var); // undefined (new_var is delcared, but not initialized) 

    var myvar = "local value"; // <-- assign the value 

    alert(zmienna); // <-- referencing the global variable 
    alert(myvar); // <-- referencing the local variable 

    var new_var = "test"; // <-- another new local variable 

    // A nested function. It has access to the variables in its scope chain. 
    (function() { 
     alert(myvar); // <-- referencing the variable from its parent func 
     alert(new_var); // <-- referencing the variable from its parent func 
    })(); 
})(); 
/* 
Here's a new function. It was not nested inside the previous function, so it 
    has access to the global variables, and not the locals of the previous func 
*/ 
(function() { 
    alert(myvar); // <-- referencing the global variable 
    alert(new_var); // <-- ReferenceError 
})(); 
+0

Muchas gracias por su respuesta. Ahora parece ser lógico. Aunque, debo admitir, para mí, Javascript es mucho más difícil que otros lenguajes que conozco (principalmente C++, PHP y Erlang). Gracias una vez más. – Radi

+0

@Radi: De nada. Tengo un poco de conocimiento de Erlang, pero no de los otros dos.Este fenómeno se llama * shadowing *, donde una función anidada puede declarar una variable con el mismo nombre que una variable en su elemento primario, y entonces, qué valor obtiene depende del nivel de la cadena de ámbito en el que se encuentra, ya que el bloque anidado acceso a los de los antepasados. Si no recuerdo mal, Erlang no permite el sombreado debido a su fuerte tipeo, pero es posible que no lo recuerde correctamente. – user113716

+0

Bueno, para ser honesto, es posible sombrear la variable en Erlang, aunque el compilador te advierte al respecto (mira esto: https://gist.github.com/1173877) – Radi

9

Se iza el uso de var.

Dado que tiene var myvar dentro de la función, existe un alcance local myvar. Dado que le asigna un valor después de alertarlo, es undefined cuando lo alerta.

+0

Bien, gracias. Pero por qué las dos primeras alertas muestran el valor correcto, a pesar de que el tutorial dice diferente (como entendí, deberían haber estado "indefinidas" ya que están en un alcance diferente). ¿Podrías explicarme eso? – Radi

+1

Porque has 'myvar' y' zmienna' declarado en alcance global. Por lo tanto, se puede acceder desde cualquier lugar de su script, si no está oculto por las definiciones de alcance locales. – J0HN

+0

@Quentin: Tal vez muestre a OP el código equivalente que demuestra a un principiante qué significa "izado" y cómo se iza la declaración, pero la asignación no lo es. – user113716