2011-02-08 15 views
6

Esta es la habitual para-loop:JavaScript for-loop alternative: repeat (n, function (i) {...});

for (var i = 0; i < n; i++) { ... } 

Se utiliza para iterar sobre arrays, sino también para simplemente repetir algún proceso n veces.

Uso el formulario mencionado anteriormente, pero me repele. El encabezado var i = 0; i < n; i++ es feo y tiene que ser reescrito literalmente cada vez que se usa.

Estoy escribiendo esta pregunta porque se me ocurrió una alternativa:

repeat(n, function(i) { ... }); 

Aquí se utiliza la función repeat que toma dos argumentos: 1.
el número de iteraciones,
2. una función qué cuerpo representa el proceso que se repite.

El "código subyacente" sería así:

function repeat(n, f) { 
    for (var i = 0; i < n; i++) { 
     f(i); 
    } 
} 

(soy consciente de las implicaciones de rendimiento de tener dos "niveles" adicionales en la cadena alcance del proceso)

BTW , para aquellos de ustedes que usan la biblioteca jQuery, la funcionalidad mencionada anteriormente se puede lograr fuera de la caja a través del método $.each así:

$.each(Array(n), function(i) { ... }); 

¿Qué piensas? ¿Es esta función repeat una alternativa válida al ciclo for nativo? ¿Cuáles son los inconvenientes de esta alternativa (aparte del rendimiento, lo sé)?

Nativo:

for (var i = 0; i < 10; i++) { 
    // do stuff 
} 

Alternativa:

repeat(10, function(i) { 
    // do stuff 
}); 
+2

lo que flota su barco hombre ... tal vez es porque he estado que codifican como 25 años, pero la OMI para (..) la sintaxis tal como está funciona bien para mí (y la sintaxis es muy similar para muchos otros idiomas) para bucles) –

+0

Una buena ventaja es que la variable 'i' no satura su alcance. Aparte de eso, tendría que decir * Meh *. :) – deceze

+0

Me gusta la idea: _code su intención, no lo que la máquina hará para lograrlo. –

Respuesta

5

es una idea interesante, pero si no le gusta la sintaxis del ciclo, siempre puede hacer una diferente tipo de bucle:

var i = arr.length; 
while (i--) { 
    // do stuff 
} 

el bucle invertido while es generalmente más rápido que un bucle for también.

+0

Hm, este bucle invertido definitivamente se ve mejor. :) –

+0

.. especialmente si está escrito en una línea: 'var i = n; mientras (i--) {'. Podría empezar a usar esto ... –

+0

Eso es bastante limpio. Podría tomar un segundo para que otro codificador lo entienda cuando lo vea por primera vez, pero parece bastante elegante. –

1

Parece bastante válida. Honestamente, no creo que el rendimiento disminuya demasiado. Pero, sin embargo, hay un gran inconveniente, que es fácilmente reparable: la declaración break.

function repeat(n, f) { 
    for (var i = 0; i < n; i++) { 
     var tcall=i; 
     tcall.die=function(){i=n} 
     f.call(tcall); 
    } 
} 

De esta manera usted sería capaz de llamar a this.die() en lugar de break; que creo que generará un error.

+0

Me gusta la idea de '.die', aunque la paso como un argumento separado. Descubrirá que la propiedad 'die' se pierde inmediatamente después de asignarla a una primitiva. –

1

Además de lo que ya ha indicado, la principal desventaja que veo es que una declaración de "devolución" funcionará de manera diferente. (Que a menudo es la razón por la que termino usando "para" más de "$ .each" muchas veces en mis propias empresas)

+0

Sí, ese es un buen punto. –

2

Para abordar la cuestión de no tener la sentencia break como otros han mencionado, me gustaría resolver de esta manera:

function repeat(n, f) { 
    for (var i = 0; i < n; i++) { 
     if (f(i) === false) return; 
    } 
} 

luego regresar false desde un controlador de bucle será equivalente a break.

Otra desventaja es que el contexto cambia. Es posible que desee añadir la opción de proxy a un contexto en los controladores de bucle:

function repeat(context, n, f) { 
    if (!f) f = n, f = context, context = window; 

    for (var i = 0; i < n; i++) { 
     if (f.call(context, i) === false) return; 
    } 
} 

Ahora, una ventaja es que el índice se mantiene por el ámbito de la función, para evitar un error común:

for (var i = 0; i < 10; i++) { 
    setTimeout(function() { 
     alert(i); // Will alert "10" every time 
    }, 1000); 
} 

repeat(10, function (i) { 
    setTimeout(function() { 
     alert(i); // Will alert "0", "1", "2", ... 
    }, 1000); 
}); 
+0

puede guardar algunos bytes allí 'if (f (i) === false) return;' – JCOC611

+0

@JCO buen punto :) –

+0

a veces es una función, no un error. Supongamos que desea encontrar un valor, o agregarlo en la parte inferior si no aparece. –

10

decir que quieres una revolución ... Bueno, ya sabes: rubí lo hizo justo antes de

Number.prototype.times = function(func) { 
    for(var i = 0; i < Number(this); i++) { 
     func(i); 
    } 
} 

significa

(?)
(50).times(function(i) { 
    console.log(i) 
}) 

De todos modos, no luchar contra C, siempre se perderá :-P

+0

Jaja, qué lindo. –