個人開発チームBUILD UP 開発者ブログ

【JavaScript】繰り返し処理の使い方と仕組みについて解説

本記事ではJavfaScriptにおける、繰り返し処理の使い方と、その仕組みについて解説します。

繰り返し処理とは、同じ処理を値を変えながら連続して行う処理のことを言います。

例えば1+X という処理に対して、Xの値を1,2,3,4・・・と変えながら連続して行い、
処理の結果として2,3,4,5,・・・と各処理の結果を取得することができます。

まず初めに繰り返し処理の方法について解説します。

繰り返し処理 for文 while文 forEach文 mapオブジェクト

まずfor文の使い方から解説します。

for文を使用すると、文の中で設定した条件が満たされるまで決められたルールによる処理が繰り返されます。

for文は初期値、終了条件、繰り返し毎のステップを記述することで繰り返し処理が実行されます。

例えば下記の条件でfor文を記述したいとします。

  • iの初期値は0とする。
  • iは繰り返し処理ごとに+1される。
  • 変数iの値が10になるまで処理を繰り返す。

for文では下記のように記述します。

for(let i = 0; i<=10; i ++){
  //繰り返し毎の処理を記述
}

()内の処理は左から「i=0」が初期値、「i<=10」が終了条件、「i ++」が繰り返しのステップです。

繰り返しステップのi ++は処理ごとにiに1を加えるという意味になります。

繰り返し処理にconsole.logを記述してみると

for(let i = 0; i<=10; i ++){
  console.log(i)
}

となります。

このように記述することでコンソールに0から10までの整数が順番に1つずつ出力されます。

続いてwhile文による繰り返し処理の記述を説明します。

while文はfor文よりもシンプルで、設定した条件を満たす(true)の場合に処理を実行します。

条件を満たさない(false)場合に繰り返しの処理が終了となります。

記述の仕方は以下となります。

let number = 0;

while(number <= 10) {
  console.log(number)
  number += 2;
}

この場合、numberの値が10以下であれば{}内の処理を実行してくれます。

numberが0から開始してコンソールに値が表示された後、numberに2が加算されます。

その後、numberの値を再度条件と照らし合わせて10以下なら繰り返し同じ処理を実行します。

したがってコンソールログには0,2,4,6,8,10の値が1つずつ表示されます。

次にforEach文について解説します。

forEach文は用意された配列に対して、配列内の値一つ一つに同じ処理を行います。

例としてAlphabetという配列を用意して、中にA~Eのアルファベットを格納しました。

配列Alphabetに対してforEach文を使用すると下記の記述になります。

const Alphabet = [A, B, C, D, E]

Alphabet.forEach( //コールバック関数を記述 )

forEachの()内にコールバック関数を記述することでA~Eの各アルファベットに対して同じ処理を行います。

これらを順番にコンソールログで表示する場合の記述は以下のようになります。

const Alphabets = [A, B, C, D, E]

Alphabets.forEach( function(Alphabet) {
  console.log(Alphabet)
})

このように記述することでコンソールにアルファベットがAから順にEまで1つずつ表示されます。

ここで、function(Alphabet)の記述は、コールバック関数内で使用する変数を定義しています。
この記述により、forEach文の中でAlphabetを記述すると配列の各値を呼び出すことができます。

配列内の値に対して、それぞれコールバック関数が実行され、配列内のすべてのデータに対して関数の実行が完了すると繰り返し処理が終了します。

最後にmapオブジェクトを解説します。

mapオブジェクトはforEach文と同じく配列に対して、コールバック関数を実行するものです。

記述例としては先ほどのforEachをmapに置き換えると同じ動作をします。

const Alphabets = [A, B, C, D, E]

Alphabets.map( function(Alphabet) {
  console.log(Alphabet)
})

この記述にて、コンソールログにAからEまでのアルファベットを1つずつ表示することができます。

繰り返いし処理においてはforEachと全く同じ挙動をしますが、mapとforEachの決定的な違いは、返り値の有無です。

forEachの場合、コールバック関数で何らかの計算を実行し、各値について繰り返し処理が完了した場合に、
計算結果を保持していません。

つまり、forEachでは、繰り返し処理の中でしかコールバック関数による結果を使用することができません。

対してmapは、繰り返し処理中にコールバック関数で処理した結果を保持しています。

これにより処理で得られた値で配列を更新し、処理完了後に更新された配列を使用することができます。

繰り返し処理の仕組みとイテレータについて

for/ofループやスプレッド演算子による繰り返し処理(反復処理)を行う際に、どのような仕組みで処理が行われているかを解説します。

反復処理は次の三つの型について理解しておく必要があります。

反復可能オブジェクト:配列 Map Set などが該当します。これらにはイテレータメソッドが含まれます。

イテレータオブジェクトnext()メソッドを持つオブジェクトのことです。

反復結果オブジェクトvalue doneプロパティを持っています。

配列やMap、Setなどを使用して、反復処理を行う場合、まず①反復可能オブジェクトのイテレータメソッド呼び出します。

このイテレータメソッドを呼び出すことで、②イテレータオブジェクトを取得することができます。

次に②イテレータオブジェクトnext()メソッドが呼び出されます。

next()メソッドを呼び出すことで③反復結果オブジェクトを取得することができます。

③反復結果オブジェクトにはdoneプロパティ(Boolean)valueプロパティが含まれており、doneプロパティがtrueになるでnextメソッドを呼び出し続けます。

この一連の流れによって繰り返しの処理が行われております。

繰り返し処理を途中で停止する ジェネレータについて

『function * 関数名』の記述にて反復処理を途中で一時停止し、値を取得することができます。

主に、処理中に待機時間が必要となるなど、同期処理として利用されますが、現在はasync/awaitを使用して非同期処理を行うことができるため、ジェネレータを使用する頻度は少なくなりました。

async/awaitによる非同期処理について詳しく知りたい方はコチラの記事を参考にしてください。

ジェネレータの使い方

Testという名前の関数をジェネレータとして記述する場合、以下のようになります。

function* Test() {
  yield 'A'
  yield 'B'
  yield 'C'
  return
}

関数名の初めにfunction*を記述することでジェネレータとしての機能を利用することができます。

そしてもう1つ重要なのが、yieldです。

繰り返し処理を一時停止するポイントをyieldで指定します。

関数Testを実行すると、先に説明したイテレータが返されます。

したがって、ジェネレータを使用する際には、next()メソッドも使用します。

実際にTestから値を取得するには以下のような記述になります。

const it = Test();
it.next(); // -> {value: 'A', done: false}
it.next(); // -> {value: 'B', done: false}
it.next(); // -> {value: 'C', done: false}
it.next(); // -> {value: undefined, done: true}

it.next()と記述することで最初のyieldの値を取得することができます。
つまり、value: Aが取得できました。

また、取得した値がイテレータなのでdoneプロパティも取得されています。
yieldが後にも控えているため、ここではdone: falseが取得されています。

次にit.next()が呼び出されるとvalue: Bとdone: falseが取得され、最後のyieldを終えて、次にit.next()が呼び出されると、done: trueが返されるので、繰り返し処理が終了します。

それぞれのit.next()の記述の間に別の処理を記述することで、繰り返し処理中に別の処理を行うことができますが、
同時に別の処理を行うことができないため、やはりasync/waitを使用して処理を実行する方が効率的です。

まとめ

  • 繰り返し処理は同じ処理を値を変えながら連続して行うことができる。
  • 主な繰り返し処理として、for文・while文・forEach文・mapオブジェクト がある。
  • 繰り返し処理を実行するとイテレータが取得され、next()メソッドを使用して呼び出される。
  • next()メソッドで得られるdoneプロパティがtrueになるまで繰り返される。
  • 関数名の頭に「function*」をつけることで途中停止できるジェネレータ機能がある。

この記事は役に立ちましたか?

もし参考になりましたら、下記のボタンで教えてください。

関連記事

コメント

この記事へのコメントはありません。