2011-08-24 16 views
54

Lectura a través de la fuente de jQuery me topé con el siguiente fragmento de código (disponible here):bucle while en lugar de

for (; i < length;) { 
    if (callback.apply(object[i++], args) === false) { 
     break; 
    } 
} 

¿Por qué es un bucle for utiliza aquí en lugar de un bucle while?

+6

Me pregunto si este código es más corto cuando se minimiza? Es un código horrible, y los chicos de jQuery son personas inteligentes, así que creo que es para propósitos de minificación. –

+9

Eliminando todos los espacios en blanco, la versión de @ aroth es más corta. Cualquier nombre de variable que pueda acortarse se usa la misma cantidad de veces. Podría ser aún más corto. 'while (i user113716

+0

Se podría argumentar que reemplazar todos los ciclos while con esta forma de for en el código minified se comprime mejor. Sin embargo, no tengo idea de si eso es lo que tenían en mente. –

Respuesta

44

Voto por alguien que tenga afinidad por el estilo de codificación incorrecto. Esa es la única explicación que puedo ver para el bucle for y el i++ que se coloca dentro de un subíndice de matriz. Creo que esto sería mejor:

while (i < length && callback.apply(object[i], args)) { 
    i++; 
} 

O si le sucede a sentir que el operador === en el ejemplo original tiene valor, entonces:

while (i < length && callback.apply(object[i], args) !== false) { 
    i++; 
} 

Otra posible razón para hacer esto puede haber sido tan una optimización del rendimiento Aunque esta rápida benchmark que puse en conjunto parece desmentir esa teoría. En Windows, el ciclo while anterior es un 20% más rápido que el círculo for original en Chrome, en IE y Firefox ambos loops funcionan igual. En OS X, el bucle for tiene una ventaja del 10% en Firefox, no hay diferencia entre los dos en Chrome, y Safari prefiere el bucle while en un 6%.

Por lo tanto, desde el punto de vista del rendimiento, es un lavado. En todo caso, a juzgar por la cuota de mercado, probablemente desee optimizar Chrome para Windows antes de optimizar para Firefox en Mac, en cuyo caso sería preferible el while.

Lo que me dice que es poco probable que la optimización del rendimiento jugó un factor con este código. Y vuelvo a mi teoría original de que es solo un ejemplo de estilo de codificación pobre que pasa el proceso de revisión del código.

+4

La estricta prueba de 'falso' es necesaria ya que ese es el * uno * valor de retorno que romperá la iteración. – user113716

+0

¿No estaría 'i' fuera por 1 en su ejemplo? – AnteSim

+0

La segunda versión es necesaria para la equivalencia con el original en los casos en que la devolución de llamada podría devolver 'undefined' o' 0'. La primera versión no funcionaría de manera idéntica en esos casos. – jfriend00

2

He encontrado que cosas como estas ocurren cuando reescribo cosas o si varias personas tocan una parte del código. No puedo ver ninguna razón en particular para eso.

espero i consigue inicializado correctamente por encima de este bloque.

6

En primer lugar, nunca hay un costo longitud para el uso de un bucle for sobre un bucle while, pero se obtiene una funcionalidad adicional con el bucle for, por lo algunos codificadores acaba de utilizar siempre el for:

for(;<condition>;){} 
while(<condition>){} 

dicho esto, creo que el propósito aquí puede ser para mantener la coherencia con el código circundante.

Por ejemplo, aquí está parte del código original. Como se puede ver, en este código puede permanecer en el "para" el modo de bucle de pensar todo el tiempo, por lo que siente más consistente:

if (args) { 
    if (isObj) { 
     for (name in object) { 
      if (callback.apply(object[name], args) === false) { 
       break; 
      } 
     } 
    } else { 
     for (; i < length;) { 
      if (callback.apply(object[i++], args) === false) { 
       break; 
      } 
     } 
    } 
} 

comparar esto con la sustitución del segundo bucle con un while.Cuando lee este código, debe pasar del modo de bucle "for" de pensamiento al modo de bucle "while". Ahora no sé ustedes, pero me resulta un poco más rápido para mis ojos para cambiar entre las condiciones de bucle anteriores en comparación con las condiciones de bucle a continuación. Esto se debe a que en el caso anterior puedo sólo se concentra en las condiciones, mientras que en el caso de abajo mis ojos se dirigen a releer el while y la for cada vez porque son diferentes:

if (args) { 
    if (isObj) { 
     for (name in object) { 
      if (callback.apply(object[name], args) === false) { 
       break; 
      } 
     } 
    } else { 
     while (i < length) { 
      if (callback.apply(object[i++], args) === false) { 
       break; 
      } 
     } 
    } 
} 
0

La más corta y más honesto la respuesta es bastante corta "solo porque". No hay absolutamente ninguna razón práctica para hacerlo, no obtenemos ningún beneficio de ese ciclo de 2 sonrisas.

En cuanto a las razones antes mencionadas, tales como:

  • refactorización - que es lo más posible, pero sin embargo esto no es una excusa.
  • consideraciones de minificación, que es menos, menos posible.
  • problemas de compatibilidad psicológica/de legibilidad/código - Tengo muchas dudas de que alguien escriba dicho código, teniendo en cuenta que un usuario puede confundirse por algunas construcciones de código y concentración suelta;

bien, por estas razones, todas ellas definitivamente vale la pena mencionar, pero, para ser honesto, el estilo del código jquery es, bueno, no es ideal. A veces hay razones por las que es así, algunas veces, es solo una cuestión de hecho.

El código de producción no siempre es el código más bonito. Leer código listo para producción, hardcore en cualquier idioma siempre es para bien, pero no es 100% sobre el estilo del código. Digamos, vim es un software hermoso, muy poderoso, pero (en mi opinión) algún purista puede sorprenderse con su código fuente. Aunque loops está bien))))

21

Aquí está the commit that introduced this oddity.

Commit mensaje: núcleo

jquery: reducción código en $.each y $.curCSS.

Recorte del diff:

-  for (var i = 0, length = object.length; i < length; i++) 
-   if (callback.apply(object[ i ], args) === false) 
+  for (; i < length;) 
+   if (callback.apply(object[ i++ ], args) === false) 

Parecería que el autor simplemente se perdió la oportunidad de cambiar el for en un while.

+0

buena llamada. esta parece ser la respuesta más probable. – wprl

0

Por lo tanto, se ejecutará al menos una vez, porque si utiliza un ciclo while si la lógica es falsa, no se ejecutará. Para lopp, incluso si es falso, se ejecutará al menos una vez.

Cuestiones relacionadas