2012-07-30 13 views
55

Nel libro JavaScript: le parti buone da Douglas Crockford, tutto questo è l'autore ha da dire circa l'istruzione continue:Perché le frasi "continue" sono errate in JavaScript?

La dichiarazione continue salta al all'inizio del ciclo. Non ho mai visto un pezzo di codice che non è stato migliorato refactoring per rimuovere l'istruzione continue.

Questo mi confonde davvero. So che Crockford ha delle opinioni molto opinate su JavaScript, ma mi sembra del tutto sbagliato.

Prima di tutto, continue fa più che saltare semplicemente all'inizio di un ciclo. Di default, progredisce anche alla successiva iterazione. Quindi la dichiarazione di Crockford non è solo un'informazione completamente falsa?

Ancora più importante, non capisco del tutto perché continue sia considerato come cattivo. Questo post fornisce quello che sembra essere il presupposto generale: Why is continue inside a loop a bad idea?

Anche se capisco come continue possono rendere il codice difficile da leggere in alcuni casi, penso che sia altrettanto probabile che possa rendere il codice più leggibile. Per esempio:

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

Questo potrebbe essere riscritta in:

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 non è particolarmente utile in questo esempio specifico, ma dimostra il fatto che esso riduce la profondità di annidamento. Nel codice più complesso, questo potrebbe aumentare la leggibilità.

Crockford non fornisce spiegazioni sul motivo per cui non si dovrebbe utilizzare continue, quindi c'è un significato più profondo dietro questa opinione che mi manca?

+0

La parola chiave 'continue' è uno strumento: utilizzalo laddove applicabile. Spesso è necessario, molte volte non lo è. L'unica volta che è brutto è quando non hai avuto bisogno di usarlo, ma sei stato troppo pigro o sciatto per farlo in un altro modo. – slugster

+0

Ho avuto la stessa sensazione ed è per questo che ho fatto il mio [post] (http://stackoverflow.com/questions/30030033/continue-statement-confusion). Ciò che mi ha aiutato è solo pensare alla parola "hop" quando si usano le istruzioni continue. Penso che Mr. Crawford abbia usato una parola povera di scelta quando ha progettato la lingua: P Soprattutto perché il luppolo può applicare la logica 'continua' dietro di esso. Se salti su qualcosa, di solito continui pure. Pensa ai maratoneti come una buona analogia. –

+4

"Mr. Crawford" non ha progettato la lingua. – rlemon

risposta

60

La dichiarazione è ridicola. continue può essere abusato, ma spesso aiuta a leggere.

uso tipico:

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

    some_provisional_work_that_is_almost_always_needed(); 

    if (!further_tests()) continue; 

    do_expensive_operation(); 
} 

L'obiettivo è quello di evitare il codice '' lasagne, dove si ha condizionali profondamente nidificate.

A cura di aggiungere:

Sì, questo è in ultima analisi soggettivo. Here's my metric for deciding.

A cura per l'ultima volta:

questo esempio è troppo semplice, ovviamente, e si può sempre sostituire condizionali nidificate con chiamate di funzione. Tuttavia, potrebbe essere necessario passare i dati nelle funzioni nidificate per riferimento, il che può creare problemi di refactoring almeno altrettanto negativi di quelli che si sta tentando di evitare.

+0

Aggiungo anche che la leggibilità è soggettiva e mentre molte persone sembrano voler continuare, altre no. Per lo stesso motivo, la gente odia il gotos, che non è intrinsecamente malvagio (solo l'abuso di gotos è malvagio). – Wug

+0

Vedere il mio post [qui] (http://stackoverflow.com/questions/30030033/continue-statement-confusion). Penso che la scelta delle parole sia semplicemente sbagliata, penso che "hop" dovrebbe essere una parola migliore usata. Ma è troppo tardi ora! –

+0

L'uso di 'continue' consente anche di leggere il codice più in uno stile * functional *, ad esempio:' for (a in b) {if (condizione1) continua; se (condizione2) continua; fare qualcosa(); } 'è simile a' b.filter (condition1) .filter (condition2) .forEach (a => ...); ' –

1

Personalmente, non ho mai sentito niente di male nell'usare l'istruzione continue.È vero che è possibile (la maggior parte delle volte) essere facilmente evitato, ma non c'è motivo di usare non. Trovo che i loop possono essere molto più chiari e più leggibili con continue dichiarazioni in atto.

+0

Così vero. Per aggiungere alla tua risposta, il transpiler aggiunge internamente l'equivalente di un'istruzione 'continue' alla fine di ogni ciclo nell'assieme generato. Quindi realisticamente, non solo le dichiarazioni continue non sono male, anzi, in realtà sono molto buone. –

2

Continua è uno strumento estremamente utile per il salvataggio dei cicli di calcolo negli algoritmi. Certo, può essere utilizzato in modo improprio, ma lo è anche per ogni altra parola chiave o approccio. Quando si cerca la performance, può essere utile adottare un approccio inverso alla divergenza del percorso con un'affermazione condizionale. Una continuazione può facilitare l'inverso consentendo di saltare i percorsi meno efficienti quando possibile.

8

Personalmente sono dall'altra parte rispetto alla maggioranza qui. Generalmente il problema non è con gli schemi continue mostrati, ma con quelli più profondamente nidificati, dove i percorsi del codice potrebbero diventare difficili da vedere.

Ma anche il tuo esempio con uno continue non mostra miglioramenti a mio avviso che sia giustificabile. Dalla mia esperienza alcune affermazioni continue sono un incubo da refactoring in seguito (anche per i linguaggi statici più adatti per il refactoring automatizzato come Java, specialmente quando qualcuno ci mette successivamente anche break).

Così, vorrei aggiungere un commento per la citazione che hai dato:

refactoring per rimuovere continue dichiarazione porta ad una crescita vostro ulteriore capacità di refactoring.

E gli anelli interni sono davvero buoni candidati per es. funzione di estrazione. Tale refactoring viene eseguito quando il loop interno diventa complesso e quindi continue potrebbe renderlo doloroso.

Queste sono le mie opinioni oneste dopo aver lavorato professionalmente su progetti JavaScript in una squadra, ci sono delle regole in base alle quali Douglas Crockford parla dei propri meriti.

+4

Non sono sicuro di sapere cosa intendi. Ti dispiacerebbe dare un esempio di dove 'continue' diventerà un" incubo da refactoring "? Inoltre, cosa intendi per "funzione di estrazione"? È un modello di design? – twiz

+2

"extract function" (può anche essere cercato su go in "extract method") è una tecnica di refactoring per estrarre parte del corpo di una funzione in una nuova funzione separata. Anche il semplice codice in un'altra risposta qui con 2 istruzioni continue dovrebbe essere riscritto (per eliminare le istruzioni continue) al fine di creare una nuova funzione fuori dal corpo del ciclo for. Quando ottieni corpi più grandi con istruzioni continue più nidificate, ci vuole un sacco di tempo per ripulire il tuo codice. –

5

Douglas Crockford può sentirsi in questo modo perché non crede nell'assegnazione entro un condizionale. In effetti, il suo programma JSlint non ti lascia nemmeno fare, anche se Javascript lo fa. Non avrebbe mai scrivere:

Esempio 1

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

    doSomething(rec); 
} 

ma, sto cercando di indovinare che sarebbe scrivere qualcosa di simile:

Esempio 2

rec = getrec(); 

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

    rec = getrec(); 
} 

Entrambi di questi lavori, ma se mescoli accidentalmente questi st yles si ottiene un ciclo infinito:

Esempio 3

rec = getrec(); 

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

    rec = getrec(); 
} 

Questo potrebbe essere parte del motivo per cui non gli piace continua.

+0

Potresti avere un punto, ma credo che in generale si opponga in generale anche agli "while while" in primo luogo. – twiz

+4

@twiz: Il mio punto si applica anche ai cicli 'for' e' do'. Sicuramente crede in * qualche * tipo di loop! –

+0

'rec = getrec();' appare due volte, violando Do not Repeat Yourself. –

2

In realtà, da tutte le analisi che sembra: - (? Inoltre, ci possono essere alcuni miglioramenti delle prestazioni)

  1. Se avete poco profonde anse Sentitevi liberi di usare continuare se e solo se migliora la leggibilità.
  2. Se si hanno loop nidificati profondi (il che significa che si ha già una palla di pelo per districare quando si ri-fattore), evitare di continuare potrebbe rivelarsi vantaggioso dal punto di vista dell'affidabilità del codice.

In difesa di Douglas Crokford, ho la sensazione che le sue raccomandazioni tendono a inclinarsi verso defensive programming, che, in tutta onestà sembra un buon approccio per 'idiot-proofing' il codice in azienda.

Problemi correlati