JavaScriptガイドパート5:配列とループ

今日、JavaScriptコースの翻訳の第5部では、配列とループについて説明します。 配列は多くの問題を解決するために使用されます。 多くの場合、ループを使用して配列を操作します。



パート1:最初のプログラム、言語機能、標準

パート2:コードスタイルとプログラム構造

パート3:変数、データ型、式、オブジェクト

パート4:機能

パート5:配列とループ

パート6:例外、セミコロン、ワイルドカードリテラル

パート7:厳格モード、このキーワード、イベント、モジュール、数学計算

パート8:ES6機能の概要

パート9:ES7、ES8、およびES9標準の概要







配列



Array型のオブジェクトであるArray



は、言語の他のメカニズムとともに進化します。 それらは番号付きの値のリストです。



配列の最初の要素にはインデックス(キー)0があり、このアプローチは多くのプログラミング言語で使用されています。



このセクションでは、配列を操作する最新の方法を検討します。



Array配列の初期化



配列を初期化する方法をいくつか示します。



 const a = [] const a = [1, 2, 3] const a = Array.of(1, 2, 3) const a = Array(6).fill(1) //   ,   6 ,  1
      
      





配列の個々の要素にアクセスするには、配列要素のインデックスを含む角括弧で構成される構造を使用します。 配列要素は読み取りまたは書き込みが可能です。



 const a = [1, 2, 3] console.log(a) //[ 1, 2, 3 ] const first = a[0] console.log(first) //1 a[0] = 4 console.log(a) //[ 4, 2, 3 ]
      
      





Array



を宣言するためのArray



コンストラクターはお勧めしません。



 const a = new Array() //  const a = new Array(1, 2, 3) // 
      
      





このメソッドは、 型付き配列を宣言する場合にのみ使用してください。



array配列の長さを取得する



配列の長さを調べるには、そのlength



プロパティを参照する必要があります。



 const l = a.length
      
      





every every()メソッドを使用して配列をチェックする



every()



配列メソッドを使用して、特定の条件を使用してすべての要素の検証を整理できます。 配列のすべての要素が条件を満たす場合、関数はtrue



を返し、そうでない場合はfalse



を返しfalse







このメソッドには、引数currentValue



(配列の現在の要素)、 index



(配列の現在の要素のindex



)、およびarray



(配列自体)をcurrentValue



関数が渡されます。 また、オプションの値を取ることもできます。 this



、渡された関数を実行するときにthis



として使用されます。

たとえば、配列内のすべての要素の値が10より大きいかどうかを確認します。



 const a = [11, 12, 13] const b = [5, 6, 25] const test = el => el > 10 console.log(a.every(test)) //true console.log(b.every(test)) //false
      
      





ここで、 test()



関数では、渡された最初の引数にのみ関心があるため、対応する値が入るel



パラメーターのみを指定して宣言します。



somesome()メソッドを使用して配列をチェックする



このメソッドはevery()



メソッドと非常に似ていますが、配列の要素の少なくとも1つが、渡された関数で指定された条件を満たす場合にtrue



返しtrue







map map()メソッドを使用して、既存の配列に基づいて配列を作成します



配列のmap()



メソッドを使用すると、配列を反復処理し、要素をこのメソッドに渡される各要素に変換する関数を適用して、受け取った値から新しい配列を作成できます。 ここでは、たとえば、元の配列のすべての要素に2を掛けた結果である新しい配列を取得する方法。



 const a = [1, 2, 3] const double = el => el * 2 const doubleA = a.map(double) console.log(a) //[ 1, 2, 3 ] console.log(doubleA) //[ 2, 4, 6 ]
      
      





filter filter()メソッドを使用して配列をフィルタリングする



filter()



メソッドはmap()



メソッドに似ていmap()



が、関数に渡されたfilter()



メソッドで指定された条件を満たす元の配列の要素のみを含む新しい配列を作成できます。



▍reduce()メソッド



reduce()



メソッドを使用すると、特定の関数をアキュムレータと配列の各値に適用して、配列を単一の値に減らすことができます(この値はプリミティブ型またはオブジェクト型のいずれかになります)。 このメソッドは、変換を実行する関数とオプションの初期バッテリー値を受け入れます。 例を考えてみましょう。



 const a = [1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => { return accumulator * currentValue }, 1) console.log(a) //24 // 1: 1 * 1 = 1 // 2: 1 * 2 = 2 // 3: 2 * 3 = 6 // 4: 6 * 4 = 24
      
      





ここでは、リテラルを使用して記述された配列のすべての要素の積を探し、アキュムレータ1の初期値を設定します。



for forEach()メソッドを使用して配列を列挙する



配列のforEach()



メソッドを使用して、配列の値を反復処理し、メソッドに渡された関数によって指定された特定のアクションを実行できます。 たとえば、コンソールの配列の要素を一度に1つずつ表示します。



 const a = [1, 2, 3] a.forEach(el => console.log(el)) //1 //2 //3
      
      





配列を繰り返し処理するときにループを停止または中断する必要がある場合は、 forEach()



使用するときに例外をスローするforEach()



があります。 したがって、特定の問題を解決する過程でループの中断が必要になる場合、配列の要素を反復処理する他の方法を選択するのが最善です。



for for ...演算子を使用して配列を選択する



for...of



演算子は、ES6標準に登場しました。 反復可能なオブジェクト(配列を含む)を反復処理できます。 使用方法は次のとおりです。



 const a = [1, 2, 3] for (let v of a) { console.log(v) } //1 //2 //3
      
      





ループの各反復で、配列a



次の要素が変数v



ます。



for forステートメントを使用して配列を列挙する



for



ステートメントを使用すると、ループを整理できます。ループを使用すると、特に、インデックスを使用して要素にアクセスして配列を反復(または初期化)できます。 通常、次の要素のインデックスはループカウンターを使用して取得されます。



 const a = [1, 2, 3] for (let i = 0; i < a.length; i += 1) { console.log(a[i]) } //1 //2 //3
      
      





ループの実行中に繰り返しをスキップする必要がある場合は、 continue



コマンドを使用できます。 サイクルを時期尚早に完了するには、 break



コマンドを使用できます。 たとえば、特定の関数にあるループでreturn



コマンドを使用すると、ループと関数は終了し、 return



return



れる値は関数が呼び出された場所に移動します。



▍メソッド@@イテレータ



このメソッドは、ES6標準に登場しました。 いわゆる「オブジェクトのイテレータ」、この場合は配列要素の反復を整理できるオブジェクトを取得できます。 配列イテレータは、シンボル(このようなシンボルは「既知のシンボル」と呼ばれます) Symbol.iterator



を使用して取得できます。 イテレータを受け取ったら、そのnext()



メソッドにアクセスできます。このメソッドは、呼び出しごとに、配列の次の要素を含むデータ構造を返します。



 const a = [1, 2, 3] let it = a[Symbol.iterator]() console.log(it.next().value) //1 console.log(it.next().value) //2 console.log(it.next().value) //3
      
      





配列の最後の要素に到達した後にnext()



メソッドを呼び出すと、要素の値としてundefined



が返されます。 next()



メソッドによって返されるオブジェクトには、 value



done



プロパティが含まdone



ます。 done



プロパティは、配列の最後の要素に到達するまでfalse



評価されfalse



。 この場合、 it.next()



を4回呼び出すと、 { value: undefined, done: true }



オブジェクトが返さ{ value: undefined, done: true }



ますが、前の3回の呼び出しではこのオブジェクトは{ value: , done: false }



ます。



entries()



配列メソッドは、配列のキーと値のペアを反復処理できる反復子を返します。



 const a = [1, 2, 3] let it = a.entries() console.log(it.next().value) //[0, 1] console.log(it.next().value) //[1, 2] console.log(it.next().value) //[2, 3]
      
      





keys()



メソッドを使用すると、配列のキーを反復処理できます。



 const a = [1, 2, 3] let it = a.keys() console.log(it.next().value) //0 console.log(it.next().value) //1 console.log(it.next().value) //2
      
      





Array配列の最後に要素を追加する



配列の最後に要素を追加するには、 push()



メソッドを使用します。



 a.push(4)
      
      





array配列の先頭に要素を追加する



配列の先頭に要素を追加するには、 unshift()



メソッドを使用します。



 a.unshift(0) a.unshift(-2, -1)
      
      





array配列要素の削除



pop()



メソッドを使用して、この要素を返しながら、配列の末尾から要素を削除できます。



 a.pop()
      
      





同様に、 shift()



メソッドを使用して、配列の先頭から要素を削除できます。



 a.shift()
      
      





同じことですが、要素の削除の位置とその番号をすでに示しているため、 splice()



メソッドを使用します。



 a.splice(0, 2) //    2     a.splice(3, 2) //    2 ,    3
      
      





array配列要素を削除し、代わりに他の要素を挿入する



何らかの操作を使用して配列の一部の要素を削除し、代わりに他の要素を挿入するには、使い慣れたsplice()



メソッドを使用します。



たとえば、ここでは、インデックス2から始まる配列の3つの要素を削除した後、同じ場所に2つの他の要素を追加します。



 const a = [1, 2, 3, 4, 5, 6] a.splice(2, 3, 'a', 'b') console.log(a) //[ 1, 2, 'a', 'b', 6 ]
      
      





multiple複数の配列を組み合わせる



複数の配列を結合するには、 concat()



メソッドを使用して、新しい配列を返します。



 const a = [1, 2] const b = [3, 4] const c = a.concat(b) console.log(c) //[ 1, 2, 3, 4 ]
      
      





array配列内のアイテムを見つける



ES5標準では、 indexOf()



メソッドが登場しました。このメソッドは、配列の必要な要素が最初に現れるインデックスを返します。 配列内で要素が見つからない場合、 -1



が返されます。



 const a = [1, 2, 3, 4, 5, 6, 7, 5, 8] console.log(a.indexOf(5)) //4 console.log(a.indexOf(23)) //-1
      
      





lastIndexOf()



メソッドは、配列内の要素の最後の出現のインデックスを返します。要素が見つからない場合は-1



返します。



 const a = [1, 2, 3, 4, 5, 6, 7, 5, 8] console.log(a.lastIndexOf(5)) //7 console.log(a.lastIndexOf(23)) //-1
      
      





ES6では、配列のfind()



メソッドが登場しました。このメソッドは、渡された関数を使用して配列検索を実行します。 関数がtrue



返すtrue



、メソッドは最初に見つかった要素の値を返します。 アイテムが見つからない場合、関数はundefined



を返します。



その使用は次のようになります。



 a.find(x => x.id === my_id)
      
      





ここでは、オブジェクトを含む配列で、 id



プロパティが指定されたものと等しい要素が検索されます。



findIndex()



メソッドはfind()



似ていますが、foundまたはundefined



要素のインデックスを返します。



ES7では、 includes()



メソッドが登場しました。これにより、配列内の特定の要素の存在を確認できます。 true



またはfalse



返し、プログラマが関心のある要素を見つけるかどうかを調べます。



 a.includes(value)
      
      





このメソッドを使用すると、このメソッドが呼び出されたときに指定されたインデックスから開始して、配列全体ではなく、特定の要素の存在をチェックできます。 インデックスは、このメソッドの2番目のオプションのパラメーターを使用して指定されます。



 a.includes(value, i)
      
      





array配列のフラグメントを取得する



配列の一部のフラグメントのコピーを新しい配列として取得するには、 slice()



メソッドを使用できます。 このメソッドが引数なしで呼び出された場合、返される配列は元の配列の完全なコピーになります。 2つのオプションパラメータが必要です。 最初はフラグメントの開始インデックスを設定し、2番目は終了を設定します。 終了インデックスが指定されていない場合、指定された開始インデックスから終了まで配列がコピーされます。



 const a = [1, 2, 3, 4, 5, 6, 7, 8, 9] console.log(a.slice(4)) //[ 5, 6, 7, 8, 9 ] console.log(a.slice(3,7)) //[ 4, 5, 6, 7 ]
      
      





array配列の並べ替え



配列要素のソートをアルファベット順( 0-9A-Za-z



)にsort()



するには、引数を渡さずにsort()



メソッドを使用します。



 const a = [1, 2, 3, 10, 11] a.sort() console.log(a) //[ 1, 10, 11, 2, 3 ] const b = [1, 'a', 'Z', 3, 2, 11] b.sort() console.log(b) //[ 1, 11, 2, 3, 'Z', 'a' ]
      
      





このメソッドにソート順を設定する関数を渡すことができます。 この関数は、2つの要素の比較のために、パラメーターa



b



受け入れます。 b



が何らかの基準でb



より小さい場合は負の数、等しい場合は0、 b



より大きい場合a



正の数を返します。 数値配列をソートする同様の関数を作成する場合、 b



b



を減算しa



結果を返すことができます。 したがって、式a - b



評価結果を返すことは、配列を昇順で並べ替えることを意味し、式b - a



の評価結果を返すことは、配列を降順で並べ替えることを意味します。



 const a = [1, 10, 3, 2, 11] console.log(a.sort((a, b) => a - b)) //[ 1, 2, 3, 10, 11 ] console.log(a.sort((a, b) => b - a)) //[ 11, 10, 3, 2, 1 ]
      
      





配列要素のシーケンスを逆にするには、 reverse()



メソッドを使用できます。 sort()



と同様に、呼び出される配列を変更します。



array配列の文字列表現を取得する



配列の文字列表現を取得するには、そのtoString()



メソッドを使用できます。



 a.toString()
      
      





同様の結果は、引数なしで呼び出されるjoin()



メソッドによって提供されます。



 a.join()
      
      





引数として要素セパレーターを渡すことができます。



 const a = [1, 10, 3, 2, 11] console.log(a.toString()) //1,10,3,2,11 console.log(a.join()) //1,10,3,2,11 console.log(a.join(', ')) //1, 10, 3, 2, 11
      
      





arrays配列のコピーを作成する



元の配列の値を新しい配列にコピーして配列のコピーを作成するには、 Array.from()



メソッドを使用できます。 また、配列のようなオブジェクト(たとえば、文字列)から配列を作成するのにも適しています。



 const a = 'a string' const b = Array.from(a) console.log(b) //[ 'a', ' ', 's', 't', 'r', 'i', 'n', 'g' ]
      
      





Array.of()



メソッドを使用して、配列をコピーしたり、さまざまな要素から配列を「アセンブル」することもできます。 たとえば、ある配列の要素を別の配列にコピーするには、次の構成を使用できます。



 const a = [1, 10, 3, 2, 11] const b = Array.of(...a) console.log(b) // [ 1, 10, 3, 2, 11 ]
      
      





copyWithin()



メソッドは、配列の要素をこの配列自体の特定の場所にコピーするために使用されます。 最初の引数はターゲット位置の初期インデックスを指定し、2番目は要素ソースの位置の初期インデックスを指定し、3番目のパラメーターはオプションで、要素ソースの位置の最終インデックスを示します。 指定しない場合、ソース位置の初期インデックスから配列の最後まで、配列の指定された場所にすべてがコピーされます。



 const a = [1, 2, 3, 4, 5] a.copyWithin(0, 2) console.log(a) //[ 3, 4, 5, 4, 5 ]
      
      





サイクル



上記の配列について言えば、ループを整理するいくつかの方法にすでに出くわしました。 ただし、JavaScriptのループは配列を操作するためだけに使用されるわけではなく、すべてのタイプとはほど遠いものと考えています。 したがって、JavaScriptでループを編成するさまざまな方法を検討することに時間を割いて、その機能について説明します。



loop forループ



このサイクルを適用する例を考えてみましょう。



 const list = ['a', 'b', 'c'] for (let i = 0; i < list.length; i++) { console.log(list[i]) //,     console.log(i) // }
      
      





既に述べたように、 break



コマンドを使用してこのようなループの実行を中断することができ、 continue



コマンドを使用して現在の反復をスキップして次の反復に直接進むことができます。



E forEachサイクル



このサイクルについても説明しました。 以下は、それを使用して配列を反復処理する例です。



 const list = ['a', 'b', 'c'] list.forEach((item, index) => { console.log(item) // console.log(index) // }) //     ,      list.forEach(item => console.log(item))
      
      





このようなサイクルを中断するには、例外をスローする必要があることを思い出してください。つまり、サイクルの使用中に例外を中断する必要がある場合は、他のサイクルを選択することをお勧めします。



▍Do ... whileループ



これは、いわゆる「事後条件サイクル」です。 このようなサイクルは、サイクルを終了する条件をチェックする前に少なくとも1回実行されます。



 const list = ['a', 'b', 'c'] let i = 0 do { console.log(list[i]) // console.log(i) // i = i + 1 } while (i < list.length)
      
      





break



コマンドを使用して中断することができ、 continue



コマンドを使用して次の反復に進むことができます。



▍whileループ



これは、いわゆる「事前調整サイクル」です。 サイクルの入り口で、サイクルを継続する条件が偽である場合、一度も実行されません。



 const list = ['a', 'b', 'c'] let i = 0 while (i < list.length) { console.log(list[i]) // console.log(i) // i = i + 1 }
      
      





... for ...ループ内



このループを使用すると、オブジェクトの列挙可能なすべてのプロパティを名前で繰り返すことができます。



 let object = {a: 1, b: 2, c: 'three'} for (let property in object) { console.log(property) //  console.log(object[property]) //  }
      
      





of〜のサイクル



for...of



サイクルは、 forEach



サイクルの利便性と、通常のツールを使用して操作を中断する機能を組み合わせています。



 //  for (const value of ['a', 'b', 'c']) { console.log(value) // } //       `entries()` for (const [index, value] of ['a', 'b', 'c'].entries()) { console.log(index) // console.log(value) // }
      
      





ここで、ループヘッダーではconst



キーワードが使用されていることに注意してください。 ループブロック内の変数を再割り当てする必要がない場合、 const



は非常に適しています。

for...in



ループとfor...of



ループを比較すると、 for...in



がプロパティの名前を繰り返し処理し、 for...in



of-プロパティの値を繰り返し処理することがわかります。



ループとスコープ



ループと変数のスコープでは、開発者にいくつかの問題を引き起こす可能性のあるJavaScript機能が1つあります。 これらの問題に対処するために、ループ、スコープ、 var



およびlet



キーワードについて説明しlet







例を考えてみましょう。



 const operations = [] for (var i = 0; i < 5; i++) { operations.push(() => {   console.log(i) }) } for (const operation of operations) { operation() }
      
      





ループは5回の反復を実行し、各反復で、 operations



配列に新しい関数が追加されます。 この関数は、ループカウンターi



値をコンソールに表示します。 関数が配列に追加された後、この配列を反復処理し、その要素である関数を呼び出します。



このようなコードを実行すると、以下に示す結果が期待できます。



 0 1 2 3 4
      
      





しかし実際、彼は次のように推測します。



 5 5 5 5 5
      
      





これはなぜですか? 問題は、ループカウンターとして、 var



キーワードを使用して宣言された変数を使用することです。



このような変数の宣言はスコープの最上部に達するため、上記のコードは次のようになります。



 var i; const operations = [] for (i = 0; i < 5; i++) { operations.push(() => {   console.log(i) }) } for (const operation of operations) { operation() }
      
      





その結果、配列を反復処理するfor...of



ループでは、変数i



がまだ表示されており、5であるため、すべての関数でi



を参照して、数値5を出力します。



プログラムに期待されることを実行するようにプログラムの動作を変更する方法は?



この問題の最も簡単な解決策は、 let



キーワードを使用するlet



です。 すでに述べたように、ES6で登場しました。その使用により、 var



特有の奇妙な部分を取り除くことができます。



特に、上記の例では、 var



let



に変更するだけで十分であり、すべてが正常に機能します。



 const operations = [] for (let i = 0; i < 5; i++) { operations.push(() => {   console.log(i) }) } for (const operation of operations) { operation() }
      
      





これで、ループの各反復で、 operations



配列に追加された各関数がi



独自のコピーを取得します。 この状況では、ループ内のi



の値が変わるため、 const



キーワードを使用できないことに注意してください。



この問題を解決する別の方法は、 let



キーワードが存在しないときにES6標準の前によく使用されていましたが、IIFEを使用することでした。



このアプローチでは、 i



の値がクロージャーに保存され、IIFEによって返され、クロージャーにアクセスできる関数が配列に入ります。 この機能は、必要に応じて実行できます。 外観は次のとおりです。



 const operations = [] for (var i = 0; i < 5; i++) { operations.push(((j) => {   return () => console.log(j) })(i)) } for (const operation of operations) { operation() }
      
      





まとめ



今日はJavaScriptの配列とループについて話しました。 次の記事のトピックは、例外処理、セミコロンの使用パターン、およびテンプレートリテラルです。



親愛なる読者! JavaScriptで配列を操作するために最も頻繁に使用する方法は何ですか?






All Articles