63

Javascript:The Good Parts by Douglas Crockford』の中で、著者が継続ステートメントについて言わなければならないのはこれだけです。

ステートメントはループのcontinue先頭にジャンプします。continueステートメントを削除するためにリファクタリングしても改善されなかったコードを見たことがありません。

これは本当に私を混乱させます。CrockfordがJavaScriptに関して非常に意見の分かれる見解を持っていることは知っていますが、これは私にはまったく間違っているように聞こえます。

まず第一にcontinue、ループの先頭にジャンプするだけではありません。デフォルトでは、次の反復にも進みます。それで、クロックフォードの声明は完全に誤った情報ではありませんか?

さらに重要なことに、私はなぜcontinue悪いとさえ見なされるのかを完全には理解していません。この投稿は、一般的な仮定と思われるものを提供します: なぜループ内で続行するのは悪い考えですか?

場合によってはコードが読みにくくなる可能性があることは理解しています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ません。それで、私が見逃しているこの意見の背後にあるより深い意味がありますか?

4

6 に答える 6

72

その声明はばかげている。continue悪用される可能性がありますが、読みやすさを向上させることがよくあります

典型的な使用法:

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

    some_provisional_work_that_is_almost_always_needed();

    if (!further_tests()) continue;

    do_expensive_operation();
}

目標は、条件が深くネストされている「ラザニア」コードを回避することです。

追加するために編集:

はい、これは最終的に主観的なものです。これが私の決定基準です。

最後にもう一度編集:

もちろん、この例は単純すぎます。ネストされた条件はいつでも関数呼び出しに置き換えることができます。ただし、参照によってネストされた関数にデータを渡す必要がある場合があります。これにより、少なくとも回避しようとしている問題と同じくらいひどいリファクタリングの問題が発生する可能性があります。

于 2012-07-30T20:04:30.083 に答える
8

私は個人的にここの大多数とは反対側にいます。問題は通常、表示されているcontinueパターンではなく、より深くネストされたパターンにあり、コードパスがわかりにくくなる可能性があります。

しかし、あなたの例でさえ、continue正当な私の意見の改善を示していません。私の経験から、いくつかのcontinueステートメントは後でリファクタリングするのは悪夢です(Javaのような自動リファクタリングに適した静的言語の場合でも、特に誰かが後でそこに置く場合break)。

したがって、私はあなたが与えた引用にコメントを追加します:

continueステートメントを削除するためのリファクタリングにより、リファクタリングの能力がさらに高まります。

そして、内側のループは、例えば、extract関数の候補として非常に適しています。このようなリファクタリングは、内側のループが複雑になり、continue痛みを伴う可能性がある場合に実行されます。

これらは、チームでJavaScriptプロジェクトに専門的に取り組んだ後の私の正直な意見です。ダグラス・クロックフォードが話しているルールは、実際にそのメリットを示しています。

于 2012-07-30T21:53:55.247 に答える
7

ダグラス・クロックフォードは、条件付きでの割り当てを信じていないため、このように感じるかもしれません。実際、彼のプログラムJSlintは、Javascriptが許可していても、それを許可していません。彼は決して書きません:

例1

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

    doSomething(rec);
}

しかし、私は彼が次のようなものを書くだろうと推測しています:

例2

rec = getrec();

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

    rec = getrec();
}

これらは両方とも機能しますが、誤ってこれらのスタイルを混在させると、無限ループが発生します。

例3

rec = getrec();

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

    rec = getrec();
}

これは、彼が継続を好まない理由の一部である可能性があります。

于 2014-07-27T01:10:44.677 に答える
2

Continueは、アルゴリズムの計算サイクルを節約するための非常に便利なツールです。もちろん、不適切に使用される可能性がありますが、他のすべてのキーワードやアプローチも同様に使用できます。パフォーマンスを追求する場合、条件付きステートメントを使用してパスの分岐に逆のアプローチをとることが役立つ場合があります。続行すると、可能であれば効率の低いパスをスキップできるため、逆の操作が容易になります。

于 2012-07-30T20:14:03.740 に答える
2

実際、すべての分析から、次のように思われます。

  1. ループが浅い場合は、読みやすさが向上する場合は、続行してください(また、パフォーマンスが向上する可能性がありますか?)。
  2. ネストされたループが深い場合(つまり、リファクタリング時に解くためのヘアボールがすでにある場合)、コードの信頼性の観点から、続行を回避することが有益であることがわかる場合があります。

Douglas Crokfordを擁護するために、彼の推奨事項は防御的なプログラミングに傾く傾向があると感じています。これは、正直なところ、企業内のコードを「ばかげた」ものにするための優れたアプローチのようです。

于 2015-05-04T09:19:34.503 に答える
1

個人的には、continueステートメントの使用について悪いことは聞いたことがありません。(ほとんどの場合)簡単に回避できることは事実ですが、使用しない理由はありません。ループは、continueステートメントを配置することで、見た目がすっきりし、読みやすくなることがわかりました。

于 2012-07-30T20:07:16.493 に答える