2010-12-18 23 views
12

He notado un comportamiento extraño de las variables en for bucles. No es realmente un problema, pero me molesta mucho.
En realidad, yo he creado dos bucles de esta manera:Confusión de alcance de variable for-loop

for (var i:uint; i<19; i++) SomeFunction (i); 
for (var i:uint; i<26; i++) SomeOtherFunction (i); 

Lo que me dieron fue una advertencia de compilación:
Warning: Duplicate variable definition.

Esta advertencia realmente me sorprendió. Nada de eso me ha pasado en otros idiomas.
Parece que la variable i entra en el ámbito que es superior en la jerarquía y queda disponible fuera del bloque del bucle. También intenté abrazar el bloque del bucle con una llave, pero no cambió nada.
¿Por qué sucede? ¿Es normal? ¿Es posible evitarlo? Por ahora acabo de establecer diferentes nombres para ambas variables, pero esa no es una solución real, creo. Realmente me gustaría utilizar la variable con nombre i en la mayoría de mis bucles for-loop.

Respuesta

14

sí, la variable de incremento de bucle está en el ámbito de la matriz bucles, no dentro del bucle en sí. Esto es intencional, por ejemplos como este:

public function getPositionOfValue (value:String) : int 
{ 
    for (var i:int = 0; i < someArray; i++) 
    { 
     if (someArray[i] == value) 
     { 
      break; 
     } 
    } 

    return i; 
} 

esto le permite acceder al valor de i una vez que el bucle ha terminado. Hay muchos casos en que esto es muy útil.

Lo que debe hacer en los casos en los que tiene múltiples bucles dentro del mismo ámbito de aplicación es el var i fuera de los bucles:

public function getPositionOfValue (value:String) : int 
{ 
    var i:int; 

    for (i = 0; i < 15; i++) 
    { 
     //do something 
    } 

    for (i = 0; i < 29; i++) 
    { 
     //do something else 
    } 

    return i; 
} 

entonces deshacerse de su advertencia. La otra cosa a considerar es nombrar las variables de incremento de bucle algo más descriptivo.

Actualización: Otros dos cosas a tener en cuenta:

1) no se debe utilizar uints excepto para cosas como los colores y los lugares donde Flex espera un uint. Son más lentos que int para usar.Fuente] 1 Actualización: parece que este puede no ser el caso en las últimas versiones del reproductor flash: source

2) cuando var una variable de incremento de bucle en el interior de una declaración de bucle, usted quiere asegurarse de que establézcalo en el valor de inicialización adecuado, generalmente 0. Puede obtener algunos errores difíciles de rastrear si no lo hace.

+0

Gracias por la respuesta significativa. :) Por cierto: 1) No sabía que 'uint' es más lento. Gracias, puede ayudarme en el futuro. 2) Lo sé, pero he leído que si un 'int' o' uint' no está inicializado, su valor es siempre 0. – rhino

+0

no hay problema, me complace ayudarlo. Re: tu respuesta a 2), eso es correcto, pero si var tu i fuera de los bucles, tu segundo bucle ahora tendrá el valor del bucle anterior. así que ten cuidado. En mi experiencia, siempre es mejor ser explícito. –

3

Declare la variable i fuera de los bucles para evitar esto. Siempre que lo restablezca (i = 0), puede usarlo en todos los bucles.

var i : uint; 
for (i=0; i<19; i++) SomeFunction(i); 
for (i=0; i<26; i++) SomeOtherFunction(i); 
6

Como se ha mencionado here, AS3 tiene un alcance global y local y eso es todo.

No hace un alcance de nivel de bloque (o para-nivel tampoco). Con el levantamiento, incluso puede escribir en variables antes de definirlas. Eso es el bit que haría mi cabeza en :-)

Las primeras versiones de Visual C tenía este error, dando lugar a todo tipo de maravillosas soluciones macro cobardes, pero esto no es un error en AS3, está funcionando como fue diseñado. Puede restringir su código para tener la declaración en el primer for solamente o mover la declaración fuera de todas las declaraciones for.

De cualquier manera, se trata de una cuestión de aceptar que el lenguaje funciona en un sentido, a pesar de que puede pensar que es una mala manera :-)