2012-07-30 2 views
55

Dans le livre Javascript: The Good Parts par Douglas Crockford, tout cela est l'auteur dit au sujet de la déclaration continue:Pourquoi les instructions "continuer" sont-elles mauvaises dans JavaScript?

sauts continue déclaration au sommet de la boucle. Je n'ai jamais vu un morceau de code qui n'a pas été amélioré en le refactorisant pour supprimer l'instruction continue.

Cela me rend vraiment confus. Je sais que Crockford a des opinions très pointues sur JavaScript, mais cela me semble complètement faux. Tout d'abord, continue fait plus que simplement sauter au sommet d'une boucle. Par défaut, il progresse également jusqu'à l'itération suivante. Donc, la déclaration de Crockford n'est-elle pas une information complètement fausse? Plus important encore, je ne comprends pas tout à fait pourquoi continue serait même considéré comme mauvais. Ce poste offre ce qui semble être l'hypothèse générale: Why is continue inside a loop a bad idea?

Bien que je comprenne comment continue peut rendre le code difficile à lire dans certains cas, je pense qu'il est tout aussi probable que cela peut rendre le code plus lisible. Par exemple:

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); 
     } 
    } 
} 

Cela pourrait être remaniée:

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 est pas particulièrement bénéfique dans cet exemple spécifique, mais cela démontre le fait qu'il réduit la profondeur d'imbrication. Dans un code plus complexe, cela pourrait potentiellement augmenter la lisibilité. Crockford ne donne aucune explication sur les raisons pour lesquelles continue ne devrait pas être utilisé, alors y a-t-il une signification plus profonde derrière cette opinion qui me manque?

+0

Le mot-clé 'continuer' est un outil - utilisez-le le cas échéant. Parfois, c'est nécessaire, la plupart du temps ce n'est pas le cas. La seule fois où c'est mauvais, c'est quand vous n'avez pas besoin de l'utiliser mais que vous êtes trop paresseux ou bâclé pour le faire d'une autre manière. – slugster

+0

J'ai eu le même sentiment et c'est pourquoi j'ai fait mon [post] (http://stackoverflow.com/questions/30030033/continue-statement-confusion). Ce qui m'a aidé est de penser au mot «hop» lorsque vous utilisez des instructions continues. Je pense que M. Crawford a utilisé un mauvais mot de choix ici lors de la conception du langage: P D'autant plus que le houblon peut appliquer la logique «continuer» derrière lui. Si vous sautez sur quelque chose, vous continuez habituellement. Pensez aux coureurs de piste de marathon comme une bonne analogie. –

+4

"M. Crawford" n'a pas conçu la langue. – rlemon

Répondre

60

La déclaration est ridicule. continue peut être abusé, mais souvent aide la lisibilité.

Utilisation typique:

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

    some_provisional_work_that_is_almost_always_needed(); 

    if (!further_tests()) continue; 

    do_expensive_operation(); 
} 

Le but est d'éviter le code 'lasagne', où vous avez conditionals profondément imbriquées.

Edité à ajouter:

Oui, cela est finalement subjective. Here's my metric for deciding.

Edité une dernière fois:

Cet exemple est trop simple, bien sûr, et vous pouvez toujours remplacer imbriqués avec des appels conditionals de fonction. Mais alors vous devrez peut-être transmettre des données dans les fonctions imbriquées par référence, ce qui peut créer des problèmes de refactorisation au moins aussi mauvais que ceux que vous essayez d'éviter.

+0

J'ajouterais aussi que la lisibilité est subjective et que si la plupart des gens semblent aimer continuer, d'autres ne le peuvent pas. Pour la même raison, les gens détestent les gotos, qui ne sont pas intrinsèquement mauvais (seul l'abus de gotos est un mal). – Wug

+0

Voir mon article [ici] (http://stackoverflow.com/questions/30030033/continue-statement-confusion). Je pense que le mot choix est juste faux, je pense que «hop» devrait être un meilleur mot utilisé. Mais c'est trop tard maintenant! –

+0

L'utilisation de 'continue' permet également de lire plus de code dans un style * fonctionnel *, par exemple:' for (a in b) {if (condition1) continue; if (condition2) continue; faire quelque chose(); } 'est similaire à' 'b.filter (condition1) .filter (condition2) .forEach (a => ...);' –

1

Personnellement, je n'ai jamais rien entendu de mal à propos de l'utilisation de l'instruction continue.Il est vrai que cela pourrait (la plupart du temps) être facilement évité, mais il n'y a aucune raison de l'utiliser. Je trouve que les boucles peuvent être beaucoup plus propres et plus lisibles avec des instructions continues en place.

+0

Tellement vrai. Pour ajouter à votre réponse, le transpiler ajoute en interne l'équivalent d'une instruction 'continue' à la fin de chaque boucle de l'assemblage généré. Donc, de façon réaliste, non seulement les énoncés continus ne sont pas mauvais, mais ils sont en fait très bons. –

2

Continue est un outil extrêmement utile pour sauvegarder des cycles de calcul dans des algorithmes. Bien sûr, il peut être utilisé de manière inappropriée, mais il en va de même pour tous les autres mots-clés ou approches. Lorsque vous recherchez des performances, il peut être utile d'adopter une approche inverse de la divergence de trajectoire avec une instruction conditionnelle. Un continue peut faciliter l'inverse en permettant à des chemins moins efficaces d'être ignorés lorsque cela est possible.

8

Je suis personnellement de l'autre côté que la majorité ici. Le problème n'est généralement pas avec les modèles continue affichés, mais avec ceux qui sont plus profondément imbriqués, où les chemins de code possibles peuvent devenir difficiles à voir.

Mais même votre exemple avec un continue ne montre pas d'amélioration à mon avis qui est justifiable. De mon expérience quelques continue déclarations sont un cauchemar pour refactoriser plus tard (même pour les langages statiques mieux adaptés pour le refactoring automatisé comme Java, surtout quand quelqu'un met plus tard break aussi).

Ainsi, je voudrais ajouter un commentaire à la citation que vous avez donné:

refactoring pour supprimer continue votre déclaration inreases plus la capacité à factoriser.

Et les boucles internes sont vraiment bien proposées, par ex. fonction d'extraction. Ce refactoring est effectué lorsque la boucle interne devient complexe, puis continue peut le rendre douloureux.

Ce sont mes opinions honnêtes après avoir travaillé professionnellement sur des projets JavaScript dans une équipe, il y a des règles dont parle Douglas Crockford vraiment montrer leurs mérites.

+4

Je ne suis pas sûr de savoir ce que vous voulez dire. Cela vous dérangerait-il de donner un exemple où «continuer» deviendra un «cauchemar à refactoriser»? Aussi, que voulez-vous dire par "fonction d'extraction"? Est-ce un motif de conception? – twiz

+2

"extraire la fonction" (peut aussi être recherché sous "méthode d'extraction") est une technique de refactoring permettant d'extraire une partie du corps d'une fonction vers une nouvelle fonction séparée. Même le code simple dans une autre réponse ici avec 2 instructions continues devrait être réécrit (pour se débarrasser des instructions continues) afin de créer une nouvelle fonction hors du corps de la boucle for. Lorsque vous obtenez des corps plus grands avec des instructions continues imbriquées, il faut beaucoup de temps pour nettoyer votre code. –

5

Douglas Crockford peut penser de cette façon parce qu'il ne croit pas à la cession dans un conditionnel. En fait, son programme JSlint ne vous permet même pas de le faire, même si Javascript le fait. Il ne serait jamais écrire:

Exemple 1

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

    doSomething(rec); 
} 

mais je devine qu'il serait écrire quelque chose comme:

Exemple 2

rec = getrec(); 

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

    rec = getrec(); 
} 

deux de ces travaux, mais si vous mélangez accidentellement ces st yles vous obtenez une boucle infinie:

Exemple 3

rec = getrec(); 

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

    rec = getrec(); 
} 

Cela pourrait faire partie des raisons pour lesquelles il n'aime pas continue.

+0

Vous pouvez avoir un point, mais je crois qu'il s'oppose aussi généralement aux boucles 'while 'en premier lieu. – twiz

+4

@twiz: Mon point s'applique également aux boucles 'for' et' do'. Il croit sûrement à * une * sorte de boucle! –

+0

'rec = getrec();' apparaît deux fois, violant Do not Repeat Yourself. –

2

En fait, de toute l'analyse, il semble: - (? Aussi, il peut avoir des gains de performance)

  1. Si vous avez des boucles peu profondes ne hésitez pas à utiliser continuer ssi il améliore la lisibilité.
  2. Si vous avez des boucles imbriquées profondes (ce qui signifie que vous avez déjà une boule de poils à démêler lorsque vous remestez le facteur), éviter de continuer peut s'avérer bénéfique du point de vue de la fiabilité du code.

En défense de Douglas Crokford, je sens que ses recommandations ont tendance à se pencher vers defensive programming, qui, en toute honnêteté semble être une bonne approche pour l'étanchéité à la con du code dans l'entreprise.

Questions connexes