2009-06-01 7 views
5

Estoy leyendo un artículo (JavaScript Closures for Dummies) y uno de los ejemplos es el siguiente.¿Cómo se hace referencia a las variables locales en los cierres?

function buildList(list) { 
    var result = []; 
    for (var i = 0; i < list.length; i++) { 
    var item = 'item' + list[i]; 
    result.push(function() {alert(item + ' ' + list[i])}); 
    } 
    return result; 
} 

function testList() { 
    var fnlist = buildList([1,2,3]); 
    // using j only to help prevent confusion - could use i 
    for (var j = 0; j < fnlist.length; j++) { 
    fnlist[j](); 
    } 
} 

testList(); 

Cuando LISTAPRUEBA se llama, un cuadro de alerta que dice "elemento3 indefinido". El artículo tiene esta explicación:

Cuando las funciones anónimas son llamados en la línea fnlist[j](); todos utilizan el mismo cierre sola, y que utilizan el valor actual de I y el tema dentro de ese un cierre (donde i tiene un valor de 3 porque el ciclo se completó, y el elemento tiene un valor de 'elemento 3').

¿Por qué el artículo tiene un valor de 'item3'? ¿No termina el bucle for cuando llego a 3? Si termina, ¿no debería el elemento seguir siendo 'item2'? ¿O es el elemento variable creado de nuevo cuando testList llama a las funciones?

+0

se trata de un error que hace más texto que pretende estar vinculado? – CookieOfFortune

Respuesta

4

Estás cerca ...

¿Por qué artículo tiene un valor de 'elemento3'? ¿No termina el bucle for cuando llego a 3?

Sí.

Si termina no debería ser el elemento 'item2'?

Nope. Este ejemplo es un poco complicado. Durante la última iteración del bucle, i es 2, pero se hace referencia a la tercera elemento de la matriz list, que es 3. En otras palabras, item == 'item' + list[2] == 'item3'

O es el elemento variable creada de nuevo cuando LISTAPRUEBA llama a las funciones ?

No, estuvo casi en lo cierto la primera vez. Creo que sólo se perdió item[2] que tiene el valor de 3.

+0

Wow eso es tan simple. ¿Cómo extrañé eso? Toda la cosa de comenzar a contar-en-cero siempre me confunde. ¡Gracias! – hekevintran

+0

Si ese fue el único obstáculo para comprender el cierre de javascript, ¡date una palmadita en la espalda! Creo que ese ejemplo fue innecesariamente complicado. – Triptych

0

El bucle termina cuando I se convierte en 3, pero el "elemento" variable almacenada en el cierre, y se muestran por alerta, está listo para

var item = 'item' + list[i]; 

el texto 'elemento' + el valor en la lista [2]. El tercer elemento de la lista es 3, por lo que el texto es item3

2

La variable list se almacena en el cierre como usted dice.

En realidad, puede acceder a la variable list, pero está intentando acceder al list[3]. Después de todo, la variable i también se almacena como cierre y su valor es 3 cuando se llama a la función console.log.

4

El bucle for dentro buildList completa antes de hacer lo siguiente:

for (var j = 0; j < fnlist.length; j++) { 
    fnlist[j](); 
} 

... por lo tanto, en ese momento (cuando se llama a cada función), la variable item será lo que fue el último asignado a él (es decir"Elemento3"), y i habrá 3 (como resultado de la última operación i++), y list[3] es undefined.

Todo tiene que ver con el hecho de que el ciclo se completa antes de llamar a la función de cierre . Para evitar esto, se podía crear un nuevo cierre, así:

function buildList(list) { 
    var result = []; 
    for (var i = 0; i < list.length; i++) { 
    var item = 'item' + list[i]; 
    result.push(
     (function(item, i){ 
      // Now we have our own "local" copies of `item` and `i` 
      return function() { 
       console.log(item + ' ' + list[i]) 
      }; 
     })(item, i) 
    ); 
    } 
    return result; 
} 
+0

@ J-P, gracias por la excelente respuesta. Ahora entiendo por qué no estaba definido, pero puedo preguntar por qué tu ejemplo funciona. ¿Por qué ahora se crea un nuevo cierre para cada una de las funciones ahora almacenadas en fnlist? – screenm0nkey

+0

Esa función que se declara y llama dentro de la llamada a "result.push" crea su propio cierre. – Pointy

+0

@Pointy, ¿por qué crea su propio cierre? Porque es una función anónima? – screenm0nkey

2

Creo que el punto se echa en falta es que se list[i] underfined porque i es 3, y list sólo está definido para 0..2.

Cuestiones relacionadas