【JavaScript 中級講座】配列の関数(forEach , map , filter)
本講座では、少し高度な配列の関数を学習する。 学習する関数は、forEach、map、filterである。
関数の引数について
これまで関数の定義方法と実行方法を、 サンプルプログラムで学習した。 すでに関数の利用方法については習得済みであると思う。 おさらいのためにサンプルを掲載する。
002//配列を作成
003const colors = [ "red" , "green" ] ;
004
005//push()関数を利用
006colors.push ( "blue" ) ;
007
008//[red green blue]
009alert ( colors.join ( " " ) ) ;
010</script>
3行目で配列を作成して変数colorsに代入し、6行目で 配列のpush()関数を実行する。 push()関数の引数に文字列を渡すと、 配列の末尾に文字列が追加される。
配列に対してpush()関数を実行する時、引数に文字列を渡す。 引数に文字列を渡すと、配列の中で適切に処理を実行し、 配列の末尾に文字列が追加される。 これが、今まで学習した関数である。
今まで学習した関数は、引数に文字列や数字を渡した。
一方、引数に「関数」を渡すことができる。
それが、今回学習する関数である。
関数B () {
//処理b
}
) ;
難しいプログラムである。後ほどステップバイステップで関数の記述方法を学習する。 まず、軽く解説する。
まず、関数Aが存在して、関数Aを実行したい。
関数Aは引数に「関数」を受け取る。
ここが今までの関数とは異なる。
引数に「文字列」や「数値」を受け取るのではない。
では、関数Aを実行する。
関数Aを実行する時、引数に自分で作成した関数Bを渡す。
関数Bを受け取った関数Aは、関数Bを実行する。
関数Bを実行すると、処理bが実行する。
JavaScriptでは、引数に関数を受け取る関数がいくつも存在する。
今回学習する、forEach、map、filterの関数は、
引数に関数を受け取る。
配列のforEach()関数を利用する
配列のforEach()関数は、配列の要素を全て取り出す時に利用する。 いままで配列の要素を取り出す時、for文を利用した。 しかし実際は、ここでご紹介するforEach()関数を利用する場合が多い。
002//配列を作成
003const colors = [ "red" , "green" ] ;
004
005//forEachを利用して配列の要素を取得
006colors.forEach (
007 function ( color , i , colors ) {
008
009 alert ( i + ":" + color ) ;
010 }
011) ;
012</script>
まず、3行目で配列colorsを宣言して配列を代入する。 6行目で配列colorsのforEach()関数を実行する。 forEach()関数は配列が持っている関数で、 配列の要素を全て取り出す機能がある。
forEach()関数は、引数に関数を受け取る。 引数の関数は7行目から10行目までである。 しかし、これでは何をやっているか分からない。
ここで解説を一時中断する。 実際に、配列のforEach()関数を書いてみよう。
003const colors = [ "red" , "green" ] ;
004
005//forEachを利用して配列の要素を取得
006colors.forEach ( ) ;
6行目で変数colorsに対してforEach()関数を実行する。 まず、配列はforEach()関数を持っている。 6行目で、配列のforEach()関数を実行する。 ここまでは今まで学習した関数と同じである。 ここから異なる。 配列のforEach()関数は、引数に関数を受け取る。 では、引数の関数を記述しよう。
003const colors = [ "red" , "green" ] ;
004
005//forEachを利用して配列の要素を取得
006colors.forEach (
007
008
009
010
011) ;
forEach()関数の括弧の終わりを、エンターキーで下の方へ移動させる。 forEach()関数の引数の括弧は、6行目から11行目までである。 6行目から11行目の括弧の中に、forEach()関数の引数に渡す関数を記述する。
003const colors = [ "red" , "green" ] ;
004
005//forEachを利用して配列の要素を取得
006colors.forEach (
007
008 function ( color , i , colors ) {
009 //処理を書く
010 }
011) ;
8行目から10行目までが、引数の関数である。
関数B () {
//処理b
}
) ;
8行目から10行目までが、関数Bに相当する。 forEach()関数を実行すると、ここで渡した関数が実行する。
第一引数 | color | 配列の値 |
第二引数 | i | 実行回数 |
第三引数 | colors | 配列 |
forEach()関数を実行すると、配列の要素の数だけ、 引数で渡した関数(関数B)が実行する。 配列の要素数が「2」の場合、引数の関数は「2」回実行する。 引数の関数が実行する時、3つの引数が渡される。 今ここで解説するよりも、具体的な値を当てはめて学習しよう。
003const colors = [ "red" , "green" ] ;
004
005//forEachを利用して配列の要素を取得
006colors.forEach (
007 function ( color , i , colors ) {
008
009 alert ( i + ":" + color ) ;
010 }
011) ;
6行目で配列のforEach()関数を実行する。 関数を実行すると、引数で渡した関数が配列の要素数、つまり「2」回実行する。 1回目に関数が実行する時、 引数にインデックス「0」の要素、「0」、配列が渡される。
004
005//forEachを利用して配列の要素を取得
006colors.forEach (
007 function ( "red" , 0 , ["red","green"] ) {
008
009 alert ( i + ":" + color ) ;
010 }
011) ;
7行目の関数に3つの引数が渡され実行される。
9行目が実行すると、「0:red」と表示する。
これが、1回目の処理である。では、2回目の処理を見る。
004
005//forEachを利用して配列の要素を取得
006colors.forEach (
007 function ( "green" , 1 , ["red","green"] ) {
008
009 alert ( i + ":" + color ) ;
010 }
011) ;
2回目の実行で、引数に「green」と「1」と「配列」が渡される。 9行目が実行すると、「1:green」と表示する。 さて、配列の要素は2つなので、以上でプログラムが終了する。
forEach()関数は、配列の全ての要素を取得する時に利用する関数である。 頻繁に利用する関数である。
配列のmap()関数を利用する
配列が持っている、map()関数を学習する。 さきほど学習したforEach()関数は、 配列の全ての要素を取り出す処理をした。 一方map()関数は、 配列内の全ての要素に、ある処理 (例えば、全ての要素に10を加算する、 全ての要素に文字列を結合する等) をする場合、利用する。 全ての要素に処理を施した後、 その新しい要素を持った新しい配列が戻る。 つまりmap()関数は、 配列の要素を元に、新しい要素を持った配列を作る。
サンプルプログラムを見る。
002//配列を作成
003const names = [ "IORI" , "iori" ] ;
004
005//mapを利用して配列の要素を処理
006const run = names.map (
007
008 function ( name , i , names ) {
009
010 return "走る" + name ;
011 }
012) ;
013
014//[走るIORI,走るiori]
015alert ( run.join ( "," ) ) ;
016</script>
配列の全ての要素に文字列「走る」を文字列結合するプログラムである。
3行目で変数namesを宣言して配列を代入する。 6行目、配列namesのmap()関数を実行する。 配列のmap()関数は、配列の全ての要素に対して何か処理をして、 処理した後の 新しい要素が入った新しい配列を戻す。 6行目の変数runで、map()関数の戻り値(新しい配列)を受け取る。
map()関数の処理内容を解説する。 map()関数の引数に関数を渡すと、 配列の要素数だけ関数が実行する。 今回、8行目から11行目までが、引数の関数である。 配列の要素数は「2」なので、引数に渡した関数が2回実行する。
第一引数 | name | 配列の値 |
第二引数 | i | 実行回数 |
第三引数 | names | 配列 |
関数が実行するたびに、引数にこれらの値が渡される。 では、関数実行1回目の場面を見る。
003const names = [ "IORI" , "iori" ] ;
004
005//mapを利用して配列の要素を処理
006const run = names.map (
007
008 function ( "IORI" , 0 , names ) {
009
010 return "走る" + name ;
011 }
012) ;
まず、8行目の引数nameに配列の最初の要素「IORI」が入り、引数iに「0」が入る。
map()関数は新しい要素をつくる関数である。 10行目に、returnキーワードがある。 新しい配列の要素にする値を、 returnキーワードの後ろに記述する。
今回、文字列「走る」を要素nameに文字列結合して、戻す。 この値が新しい要素である。 引数の関数(8行目から11行目)が実行すると、 変数runに次の配列が入る。
インデックス | 値 |
0 | 走るIORI |
さて、配列namesの要素数は2である。もう一度関数が呼ばれる。 関数が呼ばれるとき、引数に「iori」と「1」が渡される。
003const names = [ "IORI" , "iori" ] ;
004
005//mapを利用して配列の要素を処理
006const run = names.map (
007
008 function ( "iori" , 1 , names ) {
009
010 return "走る" + name ;
011 }
012) ;
10行目で新しい要素を作成する。 この関数の戻り値が新しい要素になる。 今回、文字列「走る」を変数nameの値「iori」に文字列結合する。
インデックス | 値 |
0 | 走るIORI |
1 | 走るiori |
6行目の変数runに、このような配列が入る。 配列namesの全ての要素に対して処理を実行したので、 ここでmap()関数の処理は終了する。
003const names = [ "IORI" , "iori" ] ;
004
005//mapを利用して配列の要素を処理
006const run = names.map (
007
008 function ( name , i , names ) {
009
010 return "走る" + name ;
011 }
012) ;
013
014//[走るIORI,走るiori]
015alert ( run.join ( "," ) ) ;
15行目で配列runの要素を表示すると、「走るIORI,走るiori」と表示する。
配列のfilter()関数を利用する
配列のfilter()関数を見る。 filter()関数は、条件に合う要素を配列の要素から取り出す時に利用する。 今回、配列に入った複数の数字から、「80」より大きな数字を取得する。
002//配列を作成
003const points = [ 90 , 80 , 85 ] ;
004
005//filterを利用して要素を取得
006const res = points.filter (
007
008 function ( point , i , points ) {
009
010 return point > 80 ;
011 }
012) ;
013
014//[90 85]
015alert ( res.join ( " " ) ) ;
016</script>
配列が持っている、filter()関数を学習する。
配列の要素から、ある条件に一致する要素を取り出したい時、 filter()関数を利用する。 filter()関数を実行すると、条件に一致した要素が入った 新しい配列が戻る。
004
005//filterを利用して要素を取得
006const res = points.filter (
007
008 function ( point , i , points ) {
009
010 return point > 80 ;
011 }
012) ;
プログラムを解説する。3行目で変数pointsを宣言して配列を代入する。 6行目で配列pointsに対して、filter()関数を実行する。 filter()関数の実行結果は、 条件に一致する要素が入った配列である。 6行目で変数resを宣言して、filter()関数の戻り値を受け取る。
さて、 filter()関数の引数に関数を渡す。 引数の関数は8行目から11行目までである。
004
005//filterを利用して要素を取得
006const res = points.filter (
007
008 function ( point , i , points ) {
009
010 return point > 80 ;
011 }
012) ;
引数の関数は配列pointsの要素数だけ実行する。 関数が実行するたびに、引数に値が代入される。
第一引数 | point | 配列の値 |
第二引数 | i | 実行回数 |
第三引数 | points | 配列 |
引数の内容は今までの関数と同じである。 今回、配列pointsの要素数は「3」なので、引数の関数は3回実行する。
まず1回目を見る。
004
005//filterを利用して要素を取得
006const res = points.filter (
007
008 function ( 90 , 0 , points ) {
009
010 return point > 80 ;
011 }
012) ;
関数の第一引数に「90」が入り、第二引数に「0」が入る。 filter()関数の機能は、 「条件に一致する要素を取り出し、取り出した要素を 新しい配列に代入して戻す」であった。 引数に渡した関数が「true」を戻すと、 その要素は新しい配列に代入される。 「false」を戻すと、その要素は無視され新しい配列に入らない。
今、処理中の要素は「90」である。 引数の関数で「true」を戻すと、新しい配列に「90」が入る。 「false」を戻すと、「90」は無視される。
009
010 return point > 80 ;
011 }
変数pointは「90」である。「90」は「80」よりも大きいので、 戻り値は「true」である。つまり、新しい配列に「90」が入る。 この時点で、配列resは次のようになる。
インデックス | 値 |
0 | 90 |
新しい配列resに、90が代入される。 では、2回目を見る。
004
005//filterを利用して要素を取得
006const res = points.filter (
007
008 function ( 80 , 1 , points ) {
009
010 return point > 80 ;
011 }
012) ;
変数pointの値は「80」である。関数の戻り値に注目する。「80」は「80」よりも大きくは無いので、 「false」となる。つまり、配列の要素「80」は無視され、 新しい要素には入らない。
では、3回目の処理を見る。
004
005//filterを利用して要素を取得
006const res = points.filter (
007
008 function ( 85 , 2 , points ) {
009
010 return point > 80 ;
011 }
012) ;
変数pointの値は「85」である。「80」よりも大きいので、 関数の戻り値は「true」となる。つまり、新しい配列に、要素の「80」が代入される。 以上で、全ての要素の処理が終了した。 6行目の変数resは、次のような状態である。
インデックス | 値 |
0 | 90 |
1 | 85 |
新しい配列の要素は、全て「80」より大きな値である。 さて、サンプルプログラムの最後で変数resの値を表示する。 「90 85」と表示する。