2011-04-04 14 views
11

¿Puede alguien decirme qué estoy haciendo mal aquí? Lo simplifiqué a continuación, pero básicamente estoy tratando de crear una lista y tener un evento de clic que haga referencia a una variable solo disponible en el ciclo.¿Cómo puedo pasar un parámetro de variable a una función anónima utilizando jquery?

for (var i = 0; i < data.length; i++) {                   
    $newRow = $(rowFormat);      
    $('a:first', $newRow).click(function(i){ 
    return function() { alert(i); } 
    }); 
    $list.append($newRow);  
} 
+0

Lo que hizo "mal" es llamado cierre. Le dio a cada función de clic una referencia a la misma variable 'i'. – ITroubs

+0

@ITroubs: lo sabía claramente y trató de evitarlo (de hecho, no le dio * ninguna * referencia al 'i' utilizado en el ciclo, lo sombreó en el anónimo [externo] lista de argumentos de la función). Simplemente olvidó algunos paréntesis: vea la respuesta de David. :-) –

+0

Sí, tienes razón. no leí el código correctamente ;-) – ITroubs

Respuesta

13

No está llamando a la función externa.

$('a:first', $newRow).click(function(j){ 
    return function() { alert(j); } 
}(i)); /* Pay special attention to this line, it is where the major change is */ 

As T.J. Crowder mencionado, puede mover la fábrica fuera del circuito.

function my_factory(j) { 
    return function() { 
     alert(j); 
    }; 
} 

$('a:first', $newRow).click(my_factory(i)); 
+0

Al invocar su propio argumento al hacer clic, pierde el argumento de evento que se transfiere. – Eli

+4

+1 @Mike: Le recomendaría que cambie de fábrica funcionar fuera del circuito, sin embargo; está creando innecesariamente un conjunto de funciones adicionales de fábrica, donde solo necesita una (para crear las diversas funciones para 'clic'). También recomendaría buscar la delegación de eventos en lugar de crear un controlador de eventos por separado para cada fila. –

+0

@Eli: Eso no es lo que hace el código. La función que acepta 'j' no es el manejador' click', * compila y devuelve * el manejador de clic. El controlador 'click' es la función que llama' alerta'. –

3

Ya casi lo tienes, solo un pequeño cambio. Este es en realidad mi ejemplo favorito de un uso práctico de un cierre en Javascript.

Básicamente, debe crear una función que tome un valor y devuelva una función que use ese valor. Vea la línea comentada a continuación para saber qué es lo que falta en su ejemplo. Su código creó la función anónima, pero no la invocó.

for (var i = 0; i < data.length; i++) {                   
    $newRow = $(rowFormat); 
    var fn = (function (value) { 
    return function() { 
     alert(value); 
    }; 
    }) (i); //this is what you were missing, you need to invoke the anonymous function 
    $('a:first', $newRow).click(fn); 
    $list.append($newRow);  
} 
0

Use 'bind' para adjuntar el evento 'click' y pase un parámetro. El uso de 'event.data' usted será capaz de obtener el valor correcto de su parámetro:

Ejemplo 1:

$(document).ready(function() 
{ 
    for (var i = 0; i < data.length; i++) 
    {                   
     $newRow = $(rowFormat);      
     $('a:first', $newRow).bind('click', {i: i}, 
      function (event) 
      { 
       alert(event.data.i); 
      } 
     ); 
     $list.append($newRow);  
    } 
}); 

Ejemplo 2:

$(document).ready(function() 
{ 
    $(".selectorA").each(function() 
    { 
     var elementId = $(this).attr("id"); 

     for(var i = 0; i < 20; i++) 
     { 
      $('#question' + i).bind('click', {currentIndex: i, elementId: elementId}, 
       function (event) 
       { 
        alert(event.data.currentIndex + " | " + event.data.elementId); 
       } 
      ); 
     } 
    } 
}); 
Cuestiones relacionadas