Javascriptの効率: 'for'と 'forEach' [終了]


103

for()ループと.forEachを使用したJavascriptの2017年の現在の標準は何ですか?

私は現在、UdemyでColt Steelesの「Web Dev Bootcamp」に取り組んでおり、彼は彼の教えを支持forEachforています。ただし、演​​習中にコースワークの一環としてさまざまなことを検索しましたが、for-ループではなく-ループを使用するための推奨事項が増えていますforEach。ほとんどの人はforループがより効率的であると述べているようです。

これは、コースの執筆(2015年頃)以降に変更されたものですか、それともそれぞれの長所と短所であり、より多くの経験を積んで学習します。

どんなアドバイスもいただければ幸いです。


11
なぜ2017年標準の誰かの主観的な考えに縛られるのですか?クリーンでメンテナンス可能なコードを書くなど、時代を超えた標準を採用し、エンジニアが最も一般的に使用される構成を非常に効率的にするように努力しており、特定のパフォーマンスの問題がある場合はパフォーマンスを最適化する

2
ネイティブforは純粋なスピードのために倒すのが難しいです。forEach()反復ごとにコールバックを呼び出します。そのため、明らかにそれはある程度のオーバーヘッドを伴います。
キヤノン

1
私はほとんど、またはforeachを使用しない開発者であるため、ほとんどの作業はマップ、フィルター、またはリデュースメソッドによって行われます。
AT

12
@ATは、あなたがmap純粋に反復のために使用し、それが生成する新しい配列を破棄する人でない限り、です。このサイトだけで特定の機能の選択を修正しなければならなかった人が何人いたかわかりません。
キヤノン

1
@canonは同意しました。ループの選択は重要であり、選択するときは、そのようなメソッドの出力と残りを覚えておく必要があります。読みやすさのために、単純な「forループ」は避けるべきだと思います。
AT

回答:


198

ために

forループははるかに効率的です。これは、条件がtrueである間反復するように特別に設計されたループ構造であり、同時にステップ機構を提供します(通常、反復子を増やすため)。例:

for (var i=0, n=arr.length; i < n; ++i ) {
   ...
}

JSエンジンとブラウザがforループを最適化しているため、forループが常により効率的であると示唆しているわけではありません。長年にわたって、どのループ構造がより効率的であるか(for while、reduce、reverse-whileなど)について妥協がありました。異なるブラウザーとJSエンジンには、同じ結果を生成するための異なる方法を提供する独自の実装があります。ブラウザーがパフォーマンスの要求に合わせてさらに最適化されると、理論的に[].forEachはに匹敵するより高速または同等の方法で実装できますfor

利点:

  • 効率的
  • 早期ループ終了(名誉breakcontinue
  • 条件制御(i<n配列のサイズにバインドされていない、何でもかまいません)
  • 変数のスコープ(ループの終了後に利用可能なvar ii

forEach

.forEachは主に配列(MapおよびSetオブジェクトなどの他の列挙可能なオブジェクト)を反復処理するメソッドです。それらはより新しく、主観的に読みやすいコードを提供します。例:

[].forEach((val, index)=>{
   ...
});

利点:

  • 変数の設定は含まれません(配列の各要素を繰り返します)
  • functions / arrow-functionsは、変数をブロックにスコープします。
    上の例valでは、新しく作成された関数のパラメーターになります。したがって、valループの前に呼び出された変数は、終了後に値を保持します。
  • コードが何をしているのかを特定するのが簡単になる可能性があるため、主観的に保守しやすくなります。一方、forループは、任意の数のループスキームに使用できます。

パフォーマンス

パフォーマンスはトリッキーなトピックであり、一般的に先見性やアプローチに関してある程度の経験が必要です。事前に(開発中に)どれだけの最適化が必要になるかを判断するには、プログラマーは問題のケースでの過去の経験を十分に理解し、潜在的な解決策を十分に理解している必要があります。

場合によってはjQueryの使用が遅すぎることがあります(経験豊富な開発者はそれを知っている可能性があります)。それ以外の場合は問題にならないこともあります。イベント処理)は、開発(および保守)時間を節約する価値があります。

別の例としては、パフォーマンスと最適化がすべてである場合、マシンまたはアセンブリ以外のコードはありません。多くの異なる高水準言語と低水準言語があり、それぞれに独自のトレードオフがあるため、明らかにそうではありません。これらのトレードオフには、特殊化、開発の容易さと速度、保守の容易さと速度、最適化されたコード、エラーのないコードなどが含まれますが、これらに限定されません。

アプローチ

何かが最適化されたコードを必要とするかどうかについて十分に理解していない場合、一般的には、最初に保守可能なコードを作成することをお勧めします。そこから、必要なときにさらに注意が必要なものをテストして特定できます。

とはいえ、特定の明らかな最適化は一般的な実践の一部であり、何も考える必要はありません。たとえば、次のループについて考えてみます。

for (var i=0; i < arr.length; ++i ){}

ループの反復ごとに、JavaScriptはを取得しarr.lengthます。これは、各サイクルの主要なコスト計算オペレーションです。これがあってはならない理由はありません:

for (var i=0, n=arr.length; i < n; ++i){}

これは同じことを行いますarr.lengthが、取得は1回だけで、変数をキャッシュしてコードを最適化します。


23
単一の時点、実装、またはマイクロベンチマークテストに拘束されない、優れた、徹底的で、派手でない答え。

1
パーフェクト、それはまさに私が探していたものであり、ビデオよりもはるかに深いものを提供します。私はこれを本当に感謝しています。新しいことを学ぶことはたくさんあります。これらは、将来あなたを妨げる理由がないので、一方を他方よりも優先するだけで簡単にスキップできるものです。どうもありがとう!
tonyrobbins 2017年

2
forループは、デバッグの点で利点があります。それらは、ステップイン、ブレークポイント、および検査するのが簡単です。forEach()を使用すると、追加のコールバックレベルによって状況が少し複雑になる可能性があります。
エリックグランジ

1
@FelipeBuccioniありがとうございます。実際に、エンジンが配列を変更して長さがキャッシュされているかどうかを確認するかどうかを確認すると思うので、実際に調べてみました。ただし、レガシーの目的では、最適化エンジンはそれほど寛大ではなく、長さは各反復でパフォーマンスに影響しました。私はあなたの記事を見て、時間があるときにそれを回答に組み込みます。うまくいけば、コミュニティの優れたメンバーが私のために編集として修正を加えるでしょう:)
vol7ron

6
この回答の説明とフレーズがとても楽しい[...], if performance and optimization was everything, there would be no other code than machine or assembly.です。letブロックスコープのローカル変数を宣言するためのステートメントでforEachは、のforサポートがない環境でない限り、の2番目の利点はループよりも優れているとは思いませんlet
user7393973
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.