2012-07-30 9 views
55

В книге Javascript: The Good Parts Дуглас Crockford, все это автор должен сказать о заявлении продолжения:Почему ошибки «продолжить» плохо в JavaScript?

continue оператор переходит к началу цикла. Я никогда не видел фрагмент кода, который не был улучшен путем реорганизации его, чтобы удалить оператор continue.

Это действительно смущает меня. Я знаю, что у Крокфорда есть очень упрямые взгляды на JavaScript, но это звучит совершенно неправильно для меня.

Прежде всего, continue делает больше, чем просто прыгает на вершину петли. По умолчанию он также переходит к следующей итерации. Так что заявление Крокфорда не является полностью ложной информацией?

Что еще более важно, я не совсем понимаю, почему continue будет считаться плохим. Это сообщение обеспечивает то, что, как представляется, общее предположение: Why is continue inside a loop a bad idea?

Хотя я понимаю, как continue может сделать код трудно читать в некоторых случаях, я думаю, что это так же, как вероятность того, что он может сделать код более читаемым. Например:

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

Это может быть переработан в:

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 не является особенно полезным в этом конкретном примере, но это действительно демонстрирует тот факт, что она уменьшает глубину вложенности. В более сложном коде это может повысить читаемость.

Crockford не дает никаких объяснений относительно того, почему continue не должно использоваться, так что имеет место какое-то более глубокое значение за этим мнением, что мне не хватает?

+0

Ключевое слово 'continue' - это инструмент - используйте его там, где это применимо. SOmetimes это необходимо, чаще всего это не так. Единственный раз, когда это плохо, когда вам не нужно было его использовать, но было слишком ленивым или неряшливым, чтобы сделать это по-другому. – slugster

+0

У меня было такое же чувство, и именно поэтому я сделал свой [пост] (http://stackoverflow.com/questions/30030033/continue-statement-confusion). То, что помогло мне, - просто подумать о слове 'hop' при использовании операторов continue. Я думаю, что г-н Кроуфорд использовал плохое слово выбора при разработке языка: P Тем более, что прыжок может использовать логику «продолжать» позади нее. Если вы прыгаете над чем-то, вы обычно продолжаете. Подумайте о марафонских дорожках как хорошей аналогии. –

+4

«Мистер Кроуфорд» не разрабатывал язык. – rlemon

ответ

60

Заявление нелепо. continue можно злоупотреблять, но часто помогает читаемость.

Типичное применение:

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

    some_provisional_work_that_is_almost_always_needed(); 

    if (!further_tests()) continue; 

    do_expensive_operation(); 
} 

Цель состоит в том, чтобы избежать код «лазаньи», где вы должны глубоко вложенными условными.

Edited добавить:

Да, это в конечном счете, субъективный характер. Here's my metric for deciding.

Отредактировано последний раз:

Этот пример слишком прост, конечно, и вы всегда можете заменить вложенными условными с вызовами функций. Но тогда вам, возможно, придется передавать данные во вложенные функции по ссылке, что может создавать проблемы рефакторинга, по крайней мере, такие же плохие, как те, которые вы пытаетесь избежать.

+0

Я бы также добавил, что читаемость субъективна, и в то время как большинство людей, похоже, любят использовать продолжение, другие - нет. По той же причине люди ненавидят gotos, которые не являются неотъемлемо злыми (только злоупотребление gotos является злом). – Wug

+0

Смотрите мое сообщение [здесь] (http://stackoverflow.com/questions/30030033/continue-statement-confusion). Я думаю, что выбор слова просто неправильный, я думаю, что «хоп» должен быть лучшим словом. Но уже слишком поздно! –

+0

Использование 'continue' также позволяет читать код больше в * функциональном * стиле, например:' for (a in b) {if (condition1) continue; если (условие 2) продолжается; сделай что-нибудь(); } 'аналогичен' b.filter (condition1) .filter (condition2) .forEach (a => ...); ' –

1

Лично я никогда не слышал ничего плохого в использовании инструкции continue.Это правда, что его можно (в большинстве случаев) легко избежать, но нет причин для использования не. Я нахожу, что петли могут быть более чистыми и более читабельными с продолжением утверждений.

+0

Так верно. Чтобы добавить к вашему ответу, транспилер внутренне добавляет эквивалент оператора 'continue' в конец каждого цикла в сгенерированной сборке. Так что реалистично, не только продолжают заявления не плохо, на самом деле они на самом деле очень хорошие. –

2

Continue - чрезвычайно полезный инструмент для экономии циклов вычислений в алгоритмах. Конечно, это может быть неправильно использовано, но так может быть любое другое ключевое слово или подход. При стремлении к производительности полезно использовать обратный подход к расхождению пути с условным утверждением. Продолжение может способствовать обратному, позволяя пропускать менее эффективные пути, когда это возможно.

8

Я лично с другой стороны, чем большинство здесь. Обычно проблема не связана с показанными шаблонами continue, но с более глубоко вложенными, где возможные пути кода могут стать труднодоступными.

Но даже ваш пример с одним continue не показывает улучшения, на мой взгляд, оправданным. Из моего опыта несколько заявлений continue - это кошмар для рефакторинга (даже для статических языков, более подходящих для автоматического рефакторинга, такого как Java, особенно когда кто-то позже ставит там break).

Таким образом, я хотел бы добавить комментарий к цитате вы дали:

Refactoring удалить continue заявление inreases вашей дальнейшей возможности рефакторинга, рефакторинга.

И внутренние петли действительно хорошо зарекомендовали себя, например. экстракт функция. Такой рефакторинг выполняется, когда внутренний цикл становится сложным, а затем continue может сделать его болезненным.

Это мои честные мнения после профессиональной работы над проектами JavaScript в команде, там правила, о которых говорит Дуглас Крокфорд, действительно показывают их достоинства.

+4

Я не уверен, что знаю, что вы имеете в виду. Не могли бы вы привести пример того, где «продолжить» станет «кошмаром для рефакторинга»? Кроме того, что вы подразумеваете под «функцией извлечения»? Это шаблон дизайна? – twiz

+2

«функция извлечения» (также может быть запущена в Google «метод извлечения») - это метод рефакторинга для извлечения части тела функции в новую отдельную функцию. Даже простой код в другом ответе здесь с 2 операторами продолжения должен быть переписан (чтобы избавиться от операторов continue), чтобы создать новую функцию из тела цикла for. Когда вы получаете большие тела с более вложенными операторами продолжения, для очистки вашего кода требуется много времени. –

5

Douglas Crockford может чувствовать себя так, потому что он не верит в назначение в условном выражении. Фактически, его программа JSlint даже не позволяет вам это делать, даже если Javascript это делает. Он никогда бы не написать:

Пример 1

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

    doSomething(rec); 
} 

, но я предполагаю, что он бы написать что-то вроде:

Пример 2

rec = getrec(); 

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

    rec = getrec(); 
} 

Оба из этих работ, но если вы случайно смешаете эти yles вы получите бесконечный цикл:

Пример 3

rec = getrec(); 

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

    rec = getrec(); 
} 

Это может быть частью того, почему он не любит по-прежнему.

+0

У вас может быть точка, но я считаю, что он также, как правило, выступает против петель 'while' в первую очередь. – twiz

+4

@twiz: Моя точка применяется к циклам 'for' и' do'. Конечно, он верит в * какую-то петлю! –

+0

'rec = getrec();' появляется дважды, нарушая не повторять себя. –

2

На самом деле, из всего анализа, кажется: - (? И есть может некоторый прирост производительности)

  1. Если у вас есть мелкие петли чувствуют себя свободно использовать по-прежнему тогда и только тогда она улучшает читаемость.
  2. Если у вас есть глубокие вложенные петли (что означает, что у вас уже есть шарик для распутывания при повторном коэффициенте), избегание продолжения может оказаться полезным с точки зрения надежности кода.

В защиту Дуглас Crokford, я чувствую, что его рекомендации, как правило, склоняются к defensive programming, который, по всей честности кажется хорошим подходом для «идиот-корректуры» код на предприятии.