2012-07-30 6 views
55

En el libro Javascript: las partes buenas por Douglas Crockford, esto es todo lo que el autor tiene que decir acerca de la Declaración de continuar:¿Por qué las afirmaciones "continuar" son incorrectas en JavaScript?

La declaración continue salta a la parte superior del bucle. Nunca he visto un código que no se haya mejorado al refaccionarlo para eliminar la declaración continue.

Esto realmente me confunde. Sé que Crockford tiene algunas opiniones muy dogmáticas sobre JavaScript, pero esto me suena del todo mal.

En primer lugar, continue hace más que simplemente saltar al principio de un ciclo. Por defecto, también avanza a la siguiente iteración. Entonces, ¿no es la afirmación de Crockford una información completamente falsa?

Más importante aún, no entiendo completamente por qué continue incluso se consideraría malo. Este post ofrece lo que parece ser la suposición general: Why is continue inside a loop a bad idea?

Aunque entiendo cómo continue puede hacer que el código difícil de leer en ciertos casos, creo que es tan probable que se pueda hacer el código más legible. Por ejemplo:

var someArray=['blah',5,'stuff',7]; 
for(var i=0;i<someArray.length;i++){ 
    if(typeof someArray[i]==='number'){ 
     for(var j=0;j<someArray[i];j++){ 
      console.log(j); 
     } 
    } 
} 

Esto se puede refactorizado en:

var someArray=['blah',5,'stuff',7]; 
for(var i=0;i<someArray.length;i++){ 
    if(typeof someArray[i]!=='number'){ 
     continue; 
    } 
    for(var j=0;j<someArray[i];j++){ 
     console.log(j); 
    } 
} 

continue no es particularmente beneficioso en este ejemplo específico, pero demuestra el hecho de que se reduce la profundidad de anidamiento. En un código más complejo, esto podría aumentar la legibilidad.

Crockford no proporciona ninguna explicación de por qué continue no se debe utilizar, por lo que hay una cierta importancia más profunda detrás de esta opinión que me falta?

+0

La palabra clave 'continue' es una herramienta; úsala cuando corresponda. A veces es necesario, la mayoría de las veces no lo es. La única vez que es malo es cuando no necesitas usarlo, pero eres demasiado flojo o descuidado para hacerlo de otra manera. – slugster

+0

Tuve la misma sensación y es por eso que hice mi [publicación] (http://stackoverflow.com/questions/30030033/continue-statement-confusion). Lo que me ayudó es solo pensar en la palabra 'hop' al usar las declaraciones de continuación. Creo que el Sr. Crawford usó una mala palabra de elección aquí al diseñar el lenguaje: P Especialmente porque hop puede aplicar la lógica 'continuar' detrás de él. Si saltas sobre algo, normalmente continuarás también. Piensa en los corredores de maratón como una buena analogía. –

+4

"Mr. Crawford" no diseñó el idioma. – rlemon

Respuesta

60

La declaración es ridícula. continue se puede abusar, pero a menudo ayuda a legibilidad.

Uso típico:

for (somecondition) 
{ 
    if (!firsttest) continue; 

    some_provisional_work_that_is_almost_always_needed(); 

    if (!further_tests()) continue; 

    do_expensive_operation(); 
} 

El objetivo es evitar el código '' lasaña, donde tiene condicionales anidadas.

Editado para añadir:

Sí, esto es, en última instancia subjetiva. Here's my metric for deciding.

Editado por última vez:

Este ejemplo es demasiado simple, por supuesto, y siempre se puede reemplazar a las condiciones anidadas con llamadas a funciones. Pero puede que tenga que pasar datos a las funciones anidadas por referencia, lo que puede crear problemas de refactorización al menos tan malos como los que intenta evitar.

+0

También agregaría que la legibilidad es subjetiva y, aunque a la mayoría de las personas les gusta usar continue, otras no. Por la misma razón, la gente odia a los gotos, que no son intrínsecamente malvados (solo el mal uso de gotos es malo). – Wug

+0

Ver mi publicación [aquí] (http://stackoverflow.com/questions/30030033/continue-statement-confusion). Creo que la elección de palabras es simplemente incorrecta, creo que 'hop' debería haber sido una mejor palabra utilizada. ¡Pero ya es demasiado tarde! –

+0

El uso de 'continuar' también permite leer el código más en un estilo * funcional *, por ejemplo:' para (a en b) {si (condición1) continuar; if (condición2) continuar; hacer algo(); } 'es similar a' b.filter (condition1) .filter (condition2) .forEach (a => ...); ' –

1

Personalmente, nunca escuché nada malo sobre el uso de la instrucción continue.Es cierto que podría (la mayoría de las veces) evitarse fácilmente, pero no hay ninguna razón para que no lo use. Encuentro que los bucles pueden ser mucho más limpios y legibles con declaraciones continuas en el lugar.

+0

Tan cierto. Para agregar a su respuesta, el transpiler agrega internamente el equivalente de una instrucción 'continue' al final de cada ciclo en el conjunto generado. De manera muy realista, no solo las declaraciones continuas no son malas, de hecho, en realidad son muy buenas. –

2

Continuar es una herramienta extremadamente útil para guardar ciclos de cálculo en algoritmos. Claro, se puede utilizar de manera incorrecta, pero también puede hacerlo cualquier otra palabra clave o enfoque. Al esforzarse por el rendimiento, puede ser útil adoptar un enfoque inverso a la divergencia de ruta con un enunciado condicional. Una continuación puede facilitar lo inverso al permitir que las rutas menos eficientes se omitan cuando sea posible.

8

Estoy personalmente del otro lado que la mayoría aquí. El problema generalmente no es con los patrones mostrados continue, sino con los patrones anidados más profundos, donde las posibles rutas de código pueden ser difíciles de ver.

Pero incluso su ejemplo con un continue no muestra una mejora en mi opinión que sea justificable. Desde mi experiencia, algunas declaraciones continue son una pesadilla para refactorizar más tarde (incluso para los lenguajes estáticos más adecuados para refactorización automática como Java, especialmente cuando alguien más tarde pone allí break también).

Por lo tanto, me gustaría añadir un comentario a la cita que diste:

Refactoring para eliminar continue comunicado inreases su mayor capacidad de refactorizar.

Y los bucles interiores son realmente buenos para v.g. función de extracto. Tal refactorización se realiza cuando el lazo interno se vuelve complejo y luego continue puede hacer que sea doloroso.

Estas son mis opiniones honestas después de trabajar profesionalmente en proyectos de JavaScript en un equipo, allí las reglas que Douglas Crockford habla realmente muestran sus méritos.

+4

No estoy seguro de saber a qué te refieres. ¿Le importaría dar un ejemplo de donde 'continuar 'se convertirá en una' pesadilla para refactorizar '? Además, ¿qué quiere decir con "extraer función"? ¿Es este un patrón de diseño? – twiz

+2

"función de extracción" (también se puede buscar en google en "método de extracción") es una técnica de refactorización para extraer parte del cuerpo de una función a una nueva función separada. Incluso el código simple en otra respuesta aquí con 2 sentencias continue debería ser reescrito (para deshacerse de las declaraciones continuas) para crear una nueva función fuera del cuerpo del bucle for. Cuando obtienes cuerpos más grandes con más declaraciones continuas anidadas, lleva mucho tiempo limpiar tu código. –

5

Douglas Crockford puede sentirse de esta manera porque no cree en la asignación dentro de un condicional. De hecho, su programa JSlint ni siquiera te deja hacerlo, aunque Javascript sí lo hace. Nunca escribiría:

Ejemplo 1

while (rec = getrec()) 
{ 
    if (condition1(rec)) 
     continue; 

    doSomething(rec); 
} 

pero, supongo que lo haría escribir algo como:

Ejemplo 2

rec = getrec(); 

while (rec) 
{ 
    if (!condition(rec)) 
     doSomething(rec); 

    rec = getrec(); 
} 

Tanto de estos trabajos, pero si mezcla accidentalmente estos st yles se obtiene un bucle infinito:

Ejemplo 3

rec = getrec(); 

while (rec) 
{ 
    if (condition1(rec)) 
     continue; 

    rec = getrec(); 
} 

Esto podría ser parte de la razón por la que no le gusta continúa.

+0

Puede que tengas razón, pero creo que también se opone en general a los bucles 'while' en primer lugar. – twiz

+4

@twiz: Mi punto se aplica a los bucles 'for' y' do' también. ¡Seguramente él cree en * algún tipo de bucle! –

+0

'rec = getrec();' aparece dos veces, infringiendo Do not Repeat Yourself. –

2

En realidad, de todo el análisis que parece: - (? También, hay puede haber algunas mejoras de rendimiento)

  1. Si tiene bucles superficiales no dude en utilizar continuar si y sólo si se mejora la legibilidad.
  2. Si tiene bucles anidados profundos (lo que significa que ya tiene una bola de pelo para desenredar cuando vuelve a factorizar) evitar continuar puede resultar beneficioso desde el punto de vista de la confiabilidad del código.

En defensa de Douglas Crokford, siento que sus recomendaciones tienden a inclinarse hacia defensive programming, que, con toda honestidad parece ser una buena aproximación para 'idiota a prueba' el código de la empresa.

Cuestiones relacionadas