2012-06-08 10 views
11

¿Cómo mantengo el acceso a la variable i dentro de mi ciclo for a continuación? Intento aprender, no solo obtener la respuesta, así que un poco de explicación sería muy útil. ¡Gracias!Alcance variable de Javascript dentro del ciclo

var el, 
    len = statesPolyStrings.length; 

for (var i = 0; i < len; i++) { 
    el = document.getElementById(statesPolyStrings[i]); 

    google.maps.event.addDomListener(el, 'mouseover', function() { 
     $("#"+statesPolyStrings[i]).addClass("highlight"); 
     statesPolyObjects[i].setOptions({ strokeWeight: '2' }); 
    }); 
} 
+1

¿Desea acceder a 'i' fuera del bucle for? Ya tiene acceso a 'i' dentro del ciclo for. –

+0

Quiero acceder a él dentro de la función addDomListener dentro del ciclo for. Donde quiera que vea una i en el código anterior, quiero usar i como se define e incrementar en el ciclo for. –

+1

posible duplicado de [cierre de Javascript dentro de bucles - sencillo ejemplo práctico] (http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) –

Respuesta

28

Todas sus devoluciones de llamada comparten la misma variable i.
Cuando se ejecuta realmente el controlador de eventos, i se encuentra después del final de la matriz.

Debe envolver el cuerpo del bucle en una función autoinvocada que toma i como parámetro.
De esta forma, cada iteración obtendrá su propia variable inmutable i.

Por ejemplo:

for (var i = 0; i < statesPolyStrings.length; i++) { 
    (function(i) { 
     ... 
    })(i); 
} 
+0

¿Puede dar un ejemplo mediante la corrección de mi ¿código? No estoy seguro de lo que quieres decir. –

+0

Lo tengo y ahora entiendo. Gracias. –

1
for (var i = 0; i < statesPolyStrings.length; i++) { 
    (function(i){ 
     google.maps.event.addDomListener(document.getElementById(statesPolyStrings[i]), 'mouseover', function() { 
     $("#"+statesPolyStrings[i]).addClass("highlight"); 
     statesPolyObjects[i].setOptions({ strokeWeight: '2' }); 
     }); 
    })(i) 
} 
2

El truco con funciones de auto-invocando funciona bien: se crea un nuevo ámbito de aplicación (tal vez de google para 'alcance en funciones javascript') y por lo tanto se encarga de i como diferente variable y ofrece el valor correcto para la función de devolución de llamada del oyente de eventos.

Pero en realidad no necesita para encontrar su elemento nuevo con jQuery como ya asignado un detector de eventos a la misma y dentro de su función tiene una referencia a su elemento con this.

Y como estás usando jQuery todos modos, es entonces fácil encontrar el índice correcto (su i) de statesPolyObjects con $.inArray() pasar el ID de su elemento y la matriz statesPolyStrings (suponiendo que está tratando con identificadores únicos. Si no, $("#"+statesPolyStrings[i]) también fallaría, ya que toma la primera que encuentra).

var el; 

for (var i = 0, len = statesPolyStrings.length; i < len; i++) { 
    el = document.getElementById(statesPolyStrings[i]); 

    google.maps.event.addDomListener(el, 'mouseover', function(event) { 
     $(this).addClass("highlight"); 
     statesPolyObjects[$.inArray(this.id, statesPolyStrings)]. 
      setOptions({ strokeWeight: '2' }); 
    }); 
} 

Si aún desea seguir con la función de auto-invocación de todos modos debe cambiar la siguiente línea:

("#"+statesPolyStrings[i]).addClass("highlight"); 

a

$(this).addClass("highlight"); 

Si no está lo suficientemente familiarizado con this y eventos que quizás desee leer este artículo: http://www.sitepoint.com/javascript-this-event-handlers/

Es posible que haya notado que también escribí el argumento event dentro de la función de devolución de llamada anónima. Intente console.log este evento que obtiene entregado de forma gratuita con cualquier función de devolución de llamada del oyente de eventos y explore todas las otras cosas a las que tiene acceso. Por ejemplo, puede encontrar el elemento real con el que hizo clic con event.target (ya que el mouseover real podría haberle ocurrido a un elemento secundario de su elemento). Entonces:

google.maps.event.addDomListener(el, 'mouseover', function(event) { 
    console.log(event); 
    ... 

y abra la consola de su navegador para ver qué evento ofrece ...

Tenga en cuenta que google.maps.event.addDomListener pasa algo diferente a document.body.addEventListener y también hay una diferencia entre los navegadores. jQuery.on(), por ejemplo, también ofrece algunas cosas diferentes en el objeto de evento, pero allí al menos puede contar con los mismos datos en todos los navegadores.

Cuestiones relacionadas