JavaScriptのループの違いについての詳細な説明

JavaScriptのループの違いについての詳細な説明

序文

JavaScript でループを使用する場合、列挙可能なプロパティと反復可能なオブジェクトという 2 つの重要な要素を正しく定義する必要があります。

列挙可能なプロパティ

列挙可能なオブジェクトの定義特性の 1 つは、代入演算子を使用してオブジェクトにプロパティを割り当てるときに、内部の列挙可能フラグ (enumerable) を true に設定することです。これがデフォルト値です。

ただし、これを false に設定することでこの動作を変更できます。

経験則としては、列挙可能なプロパティは常に for...in ループ内に出現します。

これを見てみましょう:

定数ユーザー = {}
users.languages ​​= 'JavaScript'
​
Object.getOwnPropertyDescriptor(ユーザー、'言語')
// 出力 -> { 値: 'JavaScript'、書き込み可能: true、列挙可能: true、構成可能: true }
​
// ループ内で使用するプロパティをより細かく制御します Object.defineProperty(users, 'role', { value: 'Admin', writable: true, enumerable: false })
​
for (const 項目 in users) {
  console.log(item) // 言語
}

ご覧のとおり、users 変数に languages プロパティを追加し、Object.getOwnPropertyDescriptor メソッドを使用して、languages プロパティ記述子の列挙可能なプロパティを true として出力しました。

Object.defineProperty を使用して role 属性を追加し、enumerable を false に設定します。role 属性は for...in ループでは出力されません。つまり、for...in ループ内のプロパティは列挙可能なプロパティです。

反復可能なオブジェクト

オブジェクトは、反復動作を定義している場合、反復可能です。この場合、for...of 構造でループされる値によって反復動作が定義されます。反復可能な組み込み型には、Array、String、Set、Map オブジェクトが含まれますが、これらは @iterator メソッドを指定していないため反復可能ではありません。

基本的に、JavaScript では、すべての反復可能なオブジェクトは列挙可能なオブジェクトですが、すべての列挙可能なオブジェクトが反復可能なオブジェクトであるとは限りません。

これを概念化する 1 つの方法は次のとおりです。for...in はデータ内のオブジェクトを検索し、for...of は繰り返しシーケンスを検索します。

配列データ型で使用した場合、これがどのように機能するかを見てみましょう。

const languages ​​= ['JavaScript', 'Python', 'Go']
​
// for...in ループで使用する for (const language in languages) {
  console.log(言語)
}
// 出力
// 0
// 1
// 2
​
// for...of ループで使用する for (const language of languages) {
  console.log(著者)
}
// 出力 -> JavaScript Python Go

この構造を使用する際に留意すべき点は、typeof が呼び出され、出力がオブジェクトである場合は、for...in ループを使用できることです。

言語変数に対するこの操作を見てみましょう。

typeof languages ​​// "object" -> なので、for inで使用できます

最初は驚くかもしれませんが、配列はインデックスによってキーが付けられる特別なタイプのオブジェクトであることに注意することが重要です。 for...in が構造内のオブジェクトを検索することを知っておくと、非常に役立ちます。 for...in ループはオブジェクトを見つけると、各キーをループします。

次のように、言語配列に対する for ..in ループの動作を視覚化できます。

定数言語 = {
  0: 'JavaScript'、
  1: 「パイソン」
  2: 「行け」
}

注: for...in は、オブジェクトまで追跡できる場合 (またはオブジェクト プロトタイプ チェーンから継承する場合)、特定の順序なしでキーを反復処理します。

また、反復子 for.. of 構造を実装すると、各反復で値がループされます。

forEachメソッドとmapメソッド

forEach メソッドと map メソッドは同じ目的を達成するために使用できますが、動作とパフォーマンス特性は異なります。

基本的なレベルでは、関数が呼び出されると、引数としてコールバックを受け取ります。

次のスニペットを検討してください。

定数スコア各 = [2, 4,8, 16, 32]
定数スコアマップ = [2, 4,8, 16, 32]
定数平方 = (数値) => 数値 * 数値

それぞれの操作の違いを詳しく見てみましょう。

forEach は undefined を返しますが、map は新しい配列を返します。

newScores = [] とします
const resultWithEach = scoresEach.forEach(スコア => {
  const newScore = square(スコア)
  新しいスコアをプッシュします
})
​
const resultWithMap = scoresMap.map(square)
​
console.log(resultWithEach) // 未定義
console.log(resultWithMap) // [4, 16, 64, 256, 1024]

Map は純粋な関数ですが、 forEach はいくつかの変更を実行します。

console.log(newScores) // [4, 16, 64, 256, 1024]

私の意見では、 map は関数型プログラミングのパラダイムをサポートしています。 forEach では newScores 変数を変更する必要がありましたが、これとは異なり、目的の結果を得るために常に変更を実行する必要はありません。各実行で同じ入力が提供されると、マップ関数は同じ結果を生成します。一方、forEach の対応する部分は、最後のミューテーションからの前の値から取得されます。

チェーン呼び出し

返される結果は配列なので、Map は呼び出しを連鎖するために使用できます。したがって、他の配列メソッドは結果に対してすぐに呼び出すことができます。つまり、filter、reduce、some などのメソッドを呼び出すことができます。戻り値が未定義であるため、forEach ではこれは不可能です。

パフォーマンス

多くの場合、map メソッドは forEach メソッドよりもパフォーマンスが優れています。

map と forEach を使用して実装された同等のコード ブロックのパフォーマンスを確認します。平均すると、マップ関数の実行速度が少なくとも 50% 速くなります。

結論は

上で説明したすべてのループ構造の中で、最も制御しやすいのは for..of ループです。キーワード return、continue、break と一緒に使用できます。つまり、配列内の各要素に対して何が起こるか、また早期に終了するかスキップするかを指定できるということです。

JavaScript のループの違いについての記事はこれで終わりです。JavaScript のループの違いについてさらに詳しく知りたい方は、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript ループトラバーサルの 24 種類のメソッドをすべてご存知ですか?
  • JavaScript イベント ループのケース スタディ
  • JavaScript における 3 つの for ループ ステートメントの使用の概要 (for、for...in、for...of)
  • jsのイベントループ機構の解析
  • JS の配列トラバーサルについて、一般的なループをいくつ知っていますか?
  • 意外と知らないJSのループ速度テストのいろいろを徹底解説
  • JavaScript で円形カルーセルを実装する
  • JavaScript の例におけるループの使用法の詳細な説明

<<:  Docker で Redis クラスターを素早く構築する方法の例

>>:  MySQL のマスタースレーブレプリケーションと読み取り書き込み分離の原理と使用法の詳細な説明

推薦する

Linux でリモートから MySQL を自動的にバックアップする方法

序文:基本的に、自社で使用する場合でも、顧客向けにサーバーを展開する場合でも、MySQL のバックア...

フレックスレイアウトではサブアイテムの高さを維持できる

Flex レイアウトを使用すると、水平に配置すると、すべての子項目の高さが同じになることがわかります...

Linuxのファイル操作の知識ポイントを詳しく解説

ファイル操作に関連するシステムコール作成するint creat(const char *ファイル名,...

Docker コンテナの正常なシャットダウン前にトラップを使用して環境のクリーンアップを実行する

実行中のコンテナが終了したときに、コンテナが完全に終了する前に環境をクリーンアップするなど、いくつか...

MySQL 8.0.18 のインストールと設定方法のグラフィックチュートリアル (Windows 10 版)

この記事は、参考のためにMySQL 8.0.18のインストールと設定のグラフィックチュートリアルを記...

Vueコンポーネント通信方法事例まとめ

目次1. 親コンポーネントが子コンポーネントに値を渡す(props) 2. サブコンポーネントは親コ...

WeChatアプレットはシンプルなチャットルームを実装します

この記事では、WeChatアプレットの具体的なコードを共有し、簡単なチャットルームを実装します。具体...

フロア効果を実現するためのJavaScript

この記事では、フロア効果を実現するためのJavaScriptの具体的なコードを参考までに紹介します。...

Windows で MySQL 5.7.17 をインストールし、エンコードを utf8 に設定する方法

ダウンロードMySQL 公式ダウンロード、Windows (x86、64 ビット)、ZIP アーカイ...

Vue大画面表示適応方法

この記事では、vueの大画面表示適応の具体的なコードを参考までに紹介します。具体的な内容は以下のとお...

vue+canvasでタイムラインを描く方法

この記事では、参考までにvueキャンバスのタイムライン描画の具体的なコードを紹介します。具体的な内容...

Web ページのエンコーディングで gbk や gb2312 ではなく utf-8 が使用されるのはなぜですか?

選択肢がある場合は、UTF-8を使用することをお勧めします。実際、Windows システム自体のプロ...

Ubuntu 20.04 は Wi-Fi に接続します (2 つの方法)

最近Ubuntu 20.04をインストールしましたが、Wi-Fiに接続できず、Wi-Fiアイコンも表...

Linux で scp コマンドを使用してファイルをリモートでコピーする方法の詳細な説明

序文scp は secure copy の略です。scp は、Linux システムの ssh ログイ...

Dockerでイメージを削除する方法

dockerでイメージを削除するコマンドはdocker rmiですが、このコマンドを実行してもイメー...