web-dev-qa-db-ja.com

forループ内で関数を使用することは悪い習慣ですか?

私は最近、ループ内で関数を呼び出すことは悪い習慣と見なされていることをどこかで読みました。これは本当ですか?たとえば、次のような場合:

function foo(value){
    console.log(value);
}

var bar = ["Foo", "Bar"];

for(var i = 0; i < bar.length; i++){
    foo(bar[i]);
}

これを行うのは悪い習慣ですか? fooを呼び出す別の方法がありますか?

注:この質問はJavaScriptに固有のものではなく、私が質問を書いたものにすぎません。

6
Robert

それは悪い習慣ではありません...それはすべて、関数が何をしているか、そして関数のコードがループ内にある必要があるかどうか、またはループの外でリファクタリングできるかどうかに依存します。

関数は単なる命令のセットであるため、理論的には、関数の命令を取得してループ内に直接配置することができ、基本的には同じです。その一連の指示が2プラス2を追加することである場合、心配する必要はあまりありません。その一連の指示が1000万行のデータベーステーブルを開き、行を見つけ、値をディスクに書き込み、接続を閉じて繰り返す場合は、何かを考える必要があります。

多くの場合、実際にかかる時間に関係なく、パフォーマンスが低くても必要な場合があります。場合によっては、実際にいくつかのばかげたものをループに入れることもできます。

「1,000万行のデータベーステーブルを開き、各行の値をファイルに書き込む」例を見てみましょう。

悪いループ:

int count = GetFullCountFromSomewhere();
for (int i = 0 i < count; i++) {
   GetMyRow(i);
   WriteMyRow(i);
}

function GetMyRow(i) {
   Table table = new Table();
   table.Fill(someConnection);
   Row row = table.Rows[i];
   return row;
}

上記では、テーブルインスタンス(および関連するすべてのオーバーヘッド)は、必ず各反復で行われます。

より良いループ:

Table table = GetMyTable()
for (int i = 0 i < table.Rows.count; i++) {
   WriteMyRow(table.Rows[i]);
}

function GetMyTable(i) {
   Table table = new Table();
   table.Fill(someConnection);
   return table;
}

または、おそらくさらに優れています(言語コンパイラによって内部的に最適化できるため)。

Table table = GetMyTable();
ForEach(var row in Table.Rows) {
    WriteMyRow(row);
}

そのため、ループ内でコードを管理する方法と、ループ外で設定する方法をいくつか紹介します。

これは、少なくとも日常的には、検討する価値のある唯一のことです。

12
jleach