2010-04-28 13 views
10

revisa el siguiente fragmento de código HTML/Javascript:¿Cuál es el alcance de una variable de Javascript declarada en un bucle for()?

<html> 
<head> 
<script type="text/javascript"> 
var alerts = []; 
for(var i = 0; i < 3; i++) { 
    alerts.push(function() { document.write(i + ', '); }); 
} 

for (var j = 0; j < 3; j++) { 
    (alerts[j])(); 
} 

for (var i = 0; i < 3; i++) { 
    (alerts[i])(); 
} 
</script> 
</head><body></body></html> 

Este salidas:

3, 3, 3, 0, 1, 2 

que no es lo que estaba esperando - que estaba esperando la salida 0, 1, 2, 0, 1, 2,

I (incorrectamente) asumió que la función anónima que se está introduciendo en la matriz se comportaría como un cierre, capturando el valor de i que se asigna cuando se crea la función, pero en realidad parece que i se está comportando como una variable global.

¿Alguien puede explicar qué ocurre con el alcance de i en este ejemplo de código y por qué la función anónima no está capturando su valor?

Respuesta

6

En Javasript, el único límite ámbito léxico "interesante" es el cuerpo de la función. Cualquier cosa declarada en cualquier parte de una función (¡bien, en cualquier lugar que no sea otra función anidada!) Está en el mismo alcance. También hay algunas cosas raras sobre la forma en que se interpretan las declaraciones.

Su función anónima sí actúa como un cierre, pero cada función instancia compartirá el mismo "i". Un truco que utilizo es añadir otra capa de función:

for (var i = 0; i < whatever; i++) { 
    (function(idaho) { 
    whatever(function() { alert("my own private " + idaho); }); 
    })(i); 
} 

En somepoint de esperar todos los navegadores apoyará la nueva declaración de "dejar", que es una menos extraño de aspecto camino más corto, para hacer básicamente la misma cosa .

8

El alcance es la función que la variable se define en (excepto no hay uno, por lo que es global).

La función anónima está de paso es acceder a la variable se define en el ámbito de la función madre (una vez más global).

Necesita un cierre real.

alerts.push(
    function (foo) { 
     return function() { 
      document.write(foo + ', '); 

     } 
    }(i) 
); 
+0

¡Respuesta correcta - gracias! - pero acepté la respuesta de Pointy porque "mi propia privacidad" + idaho me hizo reír a carcajadas ... –

Cuestiones relacionadas