JS の配列トラバーサルについて、一般的なループをいくつ知っていますか?

JS の配列トラバーサルについて、一般的なループをいくつ知っていますか?

序文

基本的なデータ構造として、配列とオブジェクトはさまざまなプログラミング言語で重要な役割を果たします。配列とオブジェクトがなければ、プログラミング言語、特に柔軟性の高い弱い型付け言語である JS がどうなるか想像するのは困難です。この記事では、一般的な配列トラバーサルとオブジェクトトラバーサルの使用法の比較と注意事項を説明します。

配列の走査

JS は開発が進むにつれて、ES7 仕様の時点で 10 を超えるトラバーサル メソッドが存在するようになりました。以下では、よく使用される配列トラバーサル方法を、同様の機能を持つグループにグループ化して紹介します。

for、forEach、for ...の

定数リスト = [1, 2, 3, 4, 5, 6, 7, 8,, 10, 11];

(i = 0, len = list.length; i < len; i++) の場合 {
  リスト[i] === 5の場合{
    ブレーク; // 1 2 3 4
    // 続行; // 1 2 3 4 6 7 8 未定義 10 11
  }
  console.log(リスト[i]);
}

for (リストのconst項目) {
  if (item === 5) {
    ブレーク; // 1 2 3 4
    // 続行; // 1 2 3 4 6 7 8 未定義 10 11
  }
  console.log(アイテム);
}

list.forEach((項目、インデックス、配列) => {
  if (item === 5) 戻り値:
  コンソール.log(インデックス); // 0 1 2 3 5 6 7 9 10
  コンソール.log(アイテム); // 1 2 3 4 6 7 8 9 10
});

まとめ

  • これら 3 つは基本的に、配列を左から右に移動します。
  • forEach はループから抜け出すことはできませんが、 for および for ..of は break または continue を使用してスキップまたは中断することができます。
  • for ...of は実際の要素に直接アクセスし、for は配列インデックスを走査し、forEach コールバック関数には豊富なパラメータがあり、要素、インデックス、元の配列をすべて取得できます。
  • 配列内に空の要素がある場合、for ...of および for も実行されます。

いくつか、すべて

定数リスト = [
  { name: 'ヘッドナビゲーション', backward: false },
  { 名前: 'カルーセル'、 後方: true }、
  { name: 'フッター', backward: false },
];
リスト内の項目を後方に並べます。
// someBackward: true
const everyNewest = list.every(item => !item.backward);
// everyNewest: false

まとめ

  • どちらも配列の条件判断を行い、ブール値を返すために使用されます。
  • どちらも中断される可能性があります。
  • 要素が条件を満たす場合は true を返し、ループは中断されます。すべての要素が条件を満たさない場合は false が返されます。
  • every は some の逆です。1 つの要素が条件を満たさない場合は false を返し、ループは中断されます。すべての要素が条件を満たす場合は true を返します。

フィルター、マップ

定数リスト = [
{ 名前: 'ヘッダーナビゲーション'、タイプ: 'nav'、ID: 1 },,
{ 名前: 'カルーセル'、タイプ: 'コンテンツ'、ID: 2 },
{ 名前: 'フッター'、タイプ: 'nav'、ID: 3 },
];
const resultList = list.filter(item => {
  console.log(アイテム);
  item.type === 'nav' を返します。
});
// 結果リスト: [
// { name: 'ヘッダーナビゲーション', type: 'nav', id: 1 },
// { 名前: 'フッター'、タイプ: 'nav'、ID: 3 },
// ]

const newList = list.map(item => {
  console.log(アイテム);
  item.id を返します。
});
// 新しいリスト: [1, 空, 2, 3]

// リスト: [
// { name: 'ヘッダーナビゲーション', type: 'nav', id: 1 },
// 空の、
// { 名前: 'カルーセル'、タイプ: 'コンテンツ'、ID: 2 },
// { 名前: 'フッター'、タイプ: 'nav'、ID: 3 },
// ]

まとめ

  • どちらも新しい配列を生成し、元の配列を変更しません (オブジェクト配列を走査するときにコールバック関数内の操作要素オブジェクトを除く)。
  • どちらも空の要素をスキップします。興味のある学生は自分で印刷することができます。
  • map はコールバック関数の戻り値で新しい配列を形成し、配列の長さは元の配列と同じになります。
  • フィルターは、コールバック関数の条件を満たす要素の新しい配列を形成します。
  • map によって生成される新しい配列要素はカスタマイズ可能です。
  • フィルターによって生成された新しい配列要素はカスタマイズできず、対応する元の配列要素と一致します。

検索、検索インデックス

定数リスト = [
{ name: 'ヘッダーナビゲーション', id: 1 },
{ 名前: 'カルーセル'、 ID: 2 }、
{ 名前: 'フッター'、 ID: 3 }、
];
const result = list.find((item) => item.id === 3);
// 結果: { name: 'Footer', id: 3 }
result.name = '下部ナビゲーション';
// リスト: [
// { name: 'ヘッダーナビゲーション', id: 1 },
// { 名前: 'カルーセル', id: 2 },
// { name: 'ボトムナビゲーション', id: 3 },
// ]

const index = list.findIndex((item) => item.id === 3);
// インデックス: 2
list[index].name // '下部ナビゲーション';

まとめ

  • どちらも配列要素を検索するために使用されます。
  • find メソッドは、コールバック関数を満たす配列の最初の要素の値を返します。存在しない場合は、undefined を返します。
  • findIndex 配列内で見つかった要素の値ではなくインデックスを返します。存在しない場合は -1 を返します。

減らす、減らす右

Reduce メソッドは 2 つのパラメーターを受け取ります。最初のパラメーターはコールバック関数 (callback) で、2 番目のパラメーターは初期値 (initialValue) です。

ReduceRight メソッドは、反対方向 (右から左) に実行される点を除いて、reduce と同じです。

コールバック関数は次の 4 つのパラメータを受け取ります。

  • accumulator: MDN では accumulator と説明されていますが、これは不適切だと思います。私の理解では、コールバック関数によって処理される現在の要素より前のすべての配列要素を累積した結果であるはずです。
  • current: 現在実行中の配列要素。
  • currentIndex: 現在実行中の配列要素のインデックス。
  • sourceArray: 元の配列、つまり、reduce メソッドが呼び出される配列。
    初期値が渡されない場合、reduce メソッドはインデックス 1 からコールバック関数を実行します。初期値が渡された場合は、インデックス 0 から開始し、初期値に基づいて累積的にコールバックを実行します。

オブジェクトの配列のプロパティの合計を計算する

定数リスト = [
  { 名前: '左'、幅: 20 },
  { 名前: 'center'、幅: 70 },
  { 名前: '右'、幅: 10 },
];
const total = list.reduce((currentTotal, item) => {
  現在の合計 + 項目の幅を返します。
}, 0);
// 合計: 100

オブジェクトの配列から重複を削除し、各項目の繰り返し回数をカウントします。

定数リスト = [
  { 名前: '左'、幅: 20 },
  { 名前: '右'、幅: 10 },
  { 名前: 'center'、幅: 70 },
  { 名前: '右'、幅: 10 },
  { 名前: '左'、幅: 20 },
  { 名前: '右'、幅: 10 },
];
定数繰り返し時間 = {};
const 結果 = list.reduce((配列、項目) => {
  if (repeatTime[item.name]) {
    repeatTime[アイテム名]++;
    配列を返します。
  }
  repeatTime[アイテム名] = 1;
  [...配列、項目]を返します。
}, []);
// 繰り返し時間: { 左: 2、右: 3、中央: 1 }
// 結果: [
// { 名前: '左'、幅: 20 },
// { 名前: 'right'、幅: 10 },
// { 名前: 'center', 幅: 70 },
// ]

オブジェクト配列の最大値/最小値を取得する

定数リスト = [
  { 名前: '左'、幅: 20 },
  { 名前: '右'、幅: 30 },
  { 名前: 'center'、幅: 70 },
  { 名前: 'top'、幅: 40 },
  { 名前: 'bottom'、幅: 20 },
];
定数max = list.reduce((curItem, item) => {
  curItem.width >= item.width を返します。curItem:item;
});
定数min = list.reduce((curItem, item) => {
  curItem.width <= item.width を返します。curItem:item;
});
// 最大: { 名前: "center", 幅: 70 }
// 最小: { 名前: "左", 幅: 20 }

Reduce は非常に強力です。さらに詳しい情報については、この記事「知っておくべき配列 Reduce の高度な使い方 25 選」をご覧ください。

パフォーマンス比較

ここまで述べてきましたが、これらのトラバーサル方法のパフォーマンスの違いは何でしょうか? Chromeブラウザで試してみましょう。各ループを10回実行し、最大値と最小値を削除して平均を取り、誤差を減らしました。

var リスト = 配列 (100000).fill(1)

コンソールで時間を指定します。
for (let index = 0, len = list.length; index < len; index++) {
}
コンソールのtimeEnd('for');
// 2.427642822265625 ミリ秒

console.time('every');
リストごとに(() => { true を返す })
console.timeEnd('every')
// 約: 2.751708984375 ミリ秒

console.time('some');
リスト.some(() => { false を返す })
console.timeEnd('some')
// 約: 2.786590576171875 ミリ秒

コンソールで時間を指定します。
リストごとに(() => {})
コンソールのtimeEnd('foreach');
// foreach: 3.126708984375 ミリ秒

コンソールに時間を表示します。
リスト.map(() => {})
コンソールのtimeEnd('マップ');
// マップ: 3.743743896484375 ミリ秒

コンソールで時間を確認します。
for (let リストのインデックス) {
}
コンソールのtimeEnd('forof')
// forof: 6.33380126953125 ミリ秒

印刷された結果から、 for ループが最も速く、 for...of ループが最も遅いことがわかります。

一般的なトラバーサルの終了とパフォーマンステーブルの比較

最後に、ブラウザカーネルによって多少の違いがありますが、興味のある学生は試してみることもできます。

オブジェクトトラバーサル

オブジェクトのトラバーサルでは、オブジェクトのキーと値をトラバースする必要があることがよくあります。ES5 では、オブジェクトをトラバースするための...in が用意されています。ただし、これには、オブジェクト プロパティの「列挙可能なプロパティ」とプロトタイプ チェーン プロパティが含まれます。以下では、Object オブジェクトの本質からオブジェクトをトラバースするさまざまな方法を検討し、一般的な方法のいくつかの特性を区別します。

のために

Object.prototype.fun = () => {};
定数obj = { 2: 'a', 1: 'b' };
(const i in obj) の場合 {
  コンソールにログ出力します。
}
// 1: ビ
// 2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 39 100 101 102 19 29 30 103 104 105 116 117 128
// fun : () => {} オブジェクトプロトタイプチェーンの拡張メソッドも走査されます for (const i in obj) {
  Object.prototype.hasOwnProperty.call(obj, i) の場合 {
      コンソールにログ出力します。
    }
}
// name : a 自分自身に属していないプロパティはhasOwnPropertyによってフィルタリングされます

まとめ

for in ループを使用すると、インスタンス内に存在するプロパティとプロトタイプ内に存在するインスタンスの両方を含む、オブジェクトを通じてアクセスできるすべての列挙可能なプロパティが返されます。オブジェクトのインスタンスのプロパティのみを取得する必要がある場合は、hasOwnProperty を使用してフィルタリングできます。

使用する場合、グローバル変数を作成する (x in a) の代わりに (const x in a) を使用します。

for in のループ順序については、[JavaScript Definitive Guide] (第 7 版) 6.6.1 を参照してください。

  • まず、名前が負でない整数である文字列属性を、最小から最大の数値の順にリストします。このルールは、配列および配列のようなオブジェクトのプロパティが順番に列挙されることを意味します。
  • 配列のようなインデックスを持つすべてのプロパティをリストした後、残りのすべてのプロパティを文字列名(整数または浮動小数点数のように見える名前を含む)でリストします。プロパティは、オブジェクトに追加された順序でリストされます。オブジェクトリテラルで定義されたプロパティは、リテラル内に表示される順序でリストされます。
  • 最後に、Symbol オブジェクトという名前のプロパティが、オブジェクトに追加された順序でリストされます。

オブジェクト.キー

Object.prototype.fun = () => {};
定数str = 'ab';
console.log(Object.keys(str));
// ['0', '1']
定数 arr = ['a', 'b'];
console.log(Object.keys(arr));
// ['0', '1']
定数obj = { 1: 'b', 0: 'a' };
console.log(Object.keys(obj));
// ['0', '1']

まとめ

プロトタイプ内のプロパティを除いて、オブジェクト自体の列挙可能なプロパティ値をすべて取得し、プロパティ名の配列を返すために使用されます。

オブジェクト.値

Object.prototype.fun = () => {};
定数str = 'ab';
console.log(Object.values(str));
// ['a', 'b']
定数 arr = ['a', 'b'];
console.log(Object.values(arr));
// ['a', 'b']
定数obj = { 1: 'b', 0: 'a' };
コンソールにログ出力します。
// ['a', 'b']

まとめ

プロトタイプ内のプロパティを除いて、オブジェクト自体の列挙可能なプロパティ値をすべて取得し、プロパティ値で構成される配列を返すために使用されます。

オブジェクト.エントリ

定数str = 'ab';
Object.entries(str) の (const [キー、値]) {
    console.log(`${キー}: ${値}`);
}
// 0: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 8
// 1: ビ
定数 arr = ['a', 'b'];
Object.entries(arr) の (const [キー、値]) {
    console.log(`${キー}: ${値}`);
}
// 0: 1 2 3 4 5 6 7 8 9 10 11 12
// 1: ビ
定数obj = { 1: 'b', 0: 'a' };
Object.entries(obj) の (const [キー、値]) {
    console.log(`${キー}: ${値}`);
}
// 0: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 8
// 1: ビ

まとめ

プロトタイプ内のプロパティを除いて、オブジェクト自体の列挙可能なプロパティ値をすべて取得し、2 次元配列を返すために使用されます。各サブ配列は、オブジェクトの属性名と属性値で構成されます。属性名と属性値の両方を取得できるメソッド。

オブジェクト.getOwnPropertyNames

Object.prototype.fun = () => {};
Array.prototype.fun = () => {};
定数str = 'ab';
console.log(Object.getOwnPropertyNames(str));
// ['0', '1', '長さ']
定数 arr = ['a', 'b'];
コンソールにログ出力します。
// ['0', '1', '長さ']
定数obj = { 1: 'b', 0: 'a' };
コンソールにログ出力します。
// ['0', '1']

まとめ

プロトタイプ内のプロパティを除いて、オブジェクト自体の列挙可能なプロパティ値をすべて取得し、プロパティ名の配列を返すために使用されます。

要約する

よく使われるいくつかのトラバーサル方法の違いを比較しました。これらを理解した後、使用する際に慎重に考える必要があり、どの方法が最も適切であるかがわかります。どなたでもコメントを修正したり追加したりしていただけます。

JS でよく使われる配列のループトラバーサルに関するこの記事はこれで終わりです。より関連性の高い JS 配列のループトラバーサルのコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

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

<<:  Windows環境でのMySQL 8.0.13無料インストールバージョンの設定チュートリアル

>>:  Centos7 システム上の nginx サーバーで Phalcon 環境を構築する方法の詳細な説明

推薦する

MySQL パフォーマンスの包括的な最適化方法リファレンス、CPU、ファイルシステムの選択から mysql.cnf パラメータの最適化まで

この記事では、一般的な MySQL 最適化方法をいくつかまとめて簡単に紹介します。これは、フルタイム...

ソースコード分析からTomcatがサーブレットの初期化を呼び出す方法の詳細な説明

目次導入1. Tomcatを起動するコード2. Tomcatフレームワーク3. コンテナを作成する ...

Vueのアイデアを使ってストレージをカプセル化する方法

目次背景関数目的アイデアの源成し遂げるセット得るプロパティの削除拡張機能を禁止するもっている要約する...

Vue+Openlayerはグラフィックスのドラッグと回転変形効果を実現します

目次序文関連資料成果を達成する実装手順序文Openlayer には独自の拡張プラグイン ol-ext...

IE6/7 は混乱するだろう: 空のテキスト ノードの高さの問題

序文: ietester でドキュメント コードを表示するには、debugbar を使用します。すべ...

マージンのマージの問題を解決する

1. 兄弟要素の余白を結合する効果は次のようになります: (2 つの間の間隔は 150 ピクセルでは...

mysqlにコメント情報を追加する実装

序文最近、MySQL に関するメモをいくつか尋ねる人がいたので、ブログ記事を書かなければなりません。...

Vueのトランジションとアニメーションの深い理解

1. DOM要素を挿入、更新、または削除するときに、適切な場合は要素にスタイルクラス名を追加します。...

MySQL 8.0 パスワード有効期限ポリシーの詳細な説明

MySQL 8.0.16 以降では、パスワードの有効期限ポリシーを設定できます。今日は、この小さな知...

MySQL での GROUP_CONCAT の使用例の分析

この記事では、例を使用して、MySQL で GROUP_CONCAT を使用する方法について説明しま...

Linux でのプロセスデーモン スーパーバイザーのインストール、構成、および使用

Supervisor は非常に優れたデーモン管理ツールです。自動起動、ログ出力、自動ログカットなど、...

JS で if 判定をスムーズに行う方法

目次序文コードの実装アイデア 1アイデア2要約する参照ドキュメント序文プロジェクト内の小さな要件ポイ...

DockerプライベートイメージライブラリとAlibaba CloudオブジェクトストレージOSSの簡単な分析

Docker プライベートイメージライブラリDockerプライベートイメージライブラリとAlibab...

Linux で time(NULL) 関数と localtime() を使用して現在の時刻を取得する方法

time(); 関数関数プロトタイプ: time_t time(time_t *timer)関数の目...

Vueドロップダウンメニューのコンポーネント開発の詳細説明

この記事の例では、Vueドロップダウンメニューのコンポーネント開発の具体的なコードを参考までに共有し...