2010-10-13 9 views
7

En el siguiente código:En un bucle, ¿se evalúa cualquier operación en la condición final en cada iteración?

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

¿La operación object.length se evalúan cada vez que en la iteración?
Tendría más sentido que el lenguaje lo evalúe una vez y guarde el resultado. Sin embargo, estaba leyendo un código en el que alguien evaluaba la operación antes de que comenzara el ciclo y la almacenaba en una variable que se usaba en la condición final.
¿Los diferentes idiomas manejan esto de manera diferente? ¿Alguna información específica para Javascript?

Respuesta

8

Obviamente, depende del idioma. Para JavaScript, la especificación (ECMAScript §12.6.3) requiere que siempre se evalúe cada vez. Como optimización, un tiempo de ejecución específico de JavaScript podría omitir una o más de las llamadas de longitud, si pudiera demostrar que el resultado no cambiará.

3

Completamente depende del idioma y (posiblemente) de lo que hay en el ciclo. El compilador/intérprete puede o no puede determinar con certeza que la propiedad "longitud" no será modificada por algo en el ciclo.

En Javascript, es una apuesta segura que se volverá a evaluar. Una referencia de propiedad simple como esa probablemente no es tan mala, pero algo así como una llamada a la función podría ser un problema de rendimiento. edit Para aclarar, con "una llamada a función" me refiero al código de cualquier forma que calcule la condición de terminación del ciclo de alguna manera lo suficientemente costosa como para hacerte sentir mal por hacerlo en cada iteración.

Por lo tanto (perdón por mi jQuery),

for (var i = 0; i < $('.foo').length; ++i) { /* ... */ } 

implicaría un recorrido de todo el DOM en cada iteración.

+1

Las llamadas a funciones no se correlacionan directamente con los problemas de rendimiento, en los lenguajes dinámicos; los cuerpos de las funciones podrían estar insertados, por ejemplo. –

+1

Y una "referencia de propiedad simple" podría estar llamando a una función getter compleja (aunque debería ser simple en este caso). –

+0

@Chris - oh sí; lo que debería haber dicho es "llamadas a funciones que hacen mucho trabajo". Puedo aclarar – Pointy

2

La condición tiene que volver a evaluarse en cada iteración del ciclo porque, en teoría, el valor podría haber cambiado dentro del cuerpo del circuito.

0

En Javascript se evalúa todo el tiempo. Se puede conseguir alrededor de él mediante el establecimiento de una variable "max" en la primera parte del bucle:

for (var i=0, imax=object.length; i<imax; i++) { 
    // statements 
} 
0

Sí, se calcula cada iteración ..

por qué no probarlo?

var loop = 5; 

for (var i = 0; i< loop; i++) 
    { 
    alert(i + ' of ' + loop); 
    loop--; 
    } 

vivo en http://jsfiddle.net/MSAdF/

2

Un compilador inteligente podría optimizar automáticamente para este caso, pero el análisis estático realizar para determinar que la longitud voluntad no cambio dentro del bucle es extremadamente difícil en JavaScript.Por esta razón, puede decir que en la mayoría de los casos object.length se reevaluará en cada iteración.

Por otro lado, a menudo es más fácil para el programador de razonar que la longitud ciertamente no cambia, y si usted es realmente (me refiero, realmente) preocupado por el rendimiento, se puede pre-cálculo y almacenar la longitud antes de que comience el ciclo.

2

Si el orden no es importante para usted, itere hacia atrás. No necesita la variable temporal sucia que contiene la longitud en este caso. El estado start del bucle solo se evalúa una vez (obviamente, sería inútil volver a evaluarlo una vez que el bucle ya haya comenzado). Mediante un ejemplo de una respuesta temprana:

for (var i = $('.foo').length - 1; i >= 0; i--) { /* ... */ } 

Sé que estoy respondiendo a este largo después de que se le pidió, pero sigue mostrando alta en los resultados de búsqueda de Google para consultas relacionadas y ninguna de las respuestas existentes parecen sugerir esto Enfoque alternativo.

+0

O 'for (var i = $ ('. Foo'). Length; i -> 0;) {/ * ... * /}' para puntos adicionales de Internet. ;) – tne

Cuestiones relacionadas