2012-06-21 11 views
5

Estoy tratando de comprender las reglas de alcance de JavaScript. Lo que he leído en los libros de texto y la documentación es confuso.JavaScript Ámbito y contexto de ejecución

Me parece que JavaScript es un lenguaje de ámbito estático (o léxico): al intentar vincular un nombre de variable a una variable (definición), se utiliza la estructura léxica del código.

Un contexto de ejecución parece ser similar a un marco de pila en la pila de llamadas. Cada contexto de ejecución tiene un objeto variable sobre el que se definen todas las variables locales (de la función asociada). Estos objetos variables se vinculan entre sí para proporcionar una 'cadena de alcance' desde el objeto variable en la parte superior de la pila hasta el objeto variable en la parte inferior de la pila (el objeto ventana). Esta cadena de ámbito se busca de arriba a abajo al vincular los nombres de las variables a las variables. Esto es muy similar a los lenguajes de ámbito estático como C/C++/Java.

Parece haber una diferencia importante con respecto a C/C++/Java: es posible acceder a una variable definida en una función cuyo marco de pila ya no está en la pila de llamadas, como se muestra en el siguiente ejemplo:

var color = "red"; 
var printColor; 

function changeColor() { 
    var color = "green"; 

    printColor = function(msg) { 
     alert(msg + color); 
    } 
    printColor("in changeColor context, color = "); // "green" 
} 

changeColor(); 

// stack frame for "changeColor" no longer on stack 
// but we can access the value of the variable color defined in that function 

printColor("in global context, color = "); // "green" 

¿Tengo este derecho? ¿Hay otros problemas que deba conocer?

Gracias de antemano

+4

Un mensaje publicado muy completo HN hoy que toca esto: [¿Cuál es el contexto de ejecución y pila en JavaScript?] (Http://davidshariff.com/blog/what-is-the-execution-context-in- javascript /) –

+2

Esto se llama * cierre *. La función que asignó a 'printColor' tiene acceso a todas las variables definidas en' changeColor' incluso después de que la función finalizó. No sé cómo es esto en C. –

+0

@FelixKling casi. sin embargo, changeColor también se define en el alcance global, por lo tanto, su alcance nunca será basura. – webduvet

Respuesta

2

Este es de hecho una gran diferencia entre C/C++ y JavaScript: JavaScript es un lenguaje de recolección de basura de referencia contado, lo que significa que los objetos pueden ser recuperados por el motor cuando ya no tiene ninguna referencia a ellos. La función que asigna a printColor no está en la pila, per se, ya que estaría en C o C++; se asigna dinámicamente y luego se asigna a una variable fuera de su alcance actual. Por lo tanto, cuando los rendimientos de flujo de control de changeColor, la función anónima todavía tiene un recuento de referencia de desde el exterior printColor se refiere a ella, y por lo tanto es utilizable a partir de la alcance exterior.

lo tanto, su ejemplo no es tanto de un problema de alcance - es claro que se declara printColor fuera del ámbito de la función de changeColor. Cuando defina changeColor, closes actualice printColor en el nuevo alcance de la función, haciéndolo accesible. Al igual que combate dijo, si se agrega un var a la segunda definición, interior del printColor, que va a shadow la primera printColor que declaró y no será accesible fuera de esa función bloque.

En cuanto a otros asuntos a tener en cuenta, sí, hay bastantes, pero vea mi comentario en su publicación original para un buen comienzo.

+0

Desgraciadamente, podría haber leído mal la pregunta (es decir, la variable 'color'), pero creo que lo que escribí todavía contiene agua. –

+0

Cuando dices que printColor no está en la pila, supongo que te refieres al objeto que representa printColor. Cuando se invoca printColor, su contexto de ejecución/marco de pila se inserta en la pila. ¿O lo he entendido mal? – asterix

0

Siempre se reduce al alcance léxico, que es la función que se ejecuta con su cadena de ámbito cuando se define, no cuando se invoca.

La función anónima se define en el ámbito local de la función changeColor en lugar del ámbito global.Por lo tanto, cuando se ejecuta de nuevo, imprime el color verde que se enumera en el ámbito local de la función changeColor.

Cuestiones relacionadas