JavaScript入門 コレクション-コールバック関数を引数に取るメソッド
配列が保持するメソッドには、コールバック関数を引数にとるものがあります。コールバック関数を引数にとるメソッドは、配列の要素に対する繰り返し処理の記述の簡略化や処理の内容を明確にする目的で使われます。
forEach 配列の各要素を使って繰り返し処理を行う
forEachメソッドを使うことで、配列の要素に対する繰り返し処理を、コールバック関数を利用して記述できます。
構文:forEachの記法
配列.forEach( function( value, index, arry ) {
/* 配列の各要素を使った処理 */
} [, _this]);
- value:配列の値が1つずつ渡されてきます。
- index:配列のインデックスが1つずつ渡されてきます。
- arry:配列自体が渡されます。
- _this:コールバック関数内のthisの参照先を設定します。
使用例
const arry = [1, 2, 3, 4, 5];
arry.forEach( function( value, index, arry ){
console.log( value, index, arry );
} );
forEachでは、コールバック関数の引数として値、インデックス、配列自身がそれぞれ渡されます。
上記のコードと同じ処理をfor文を使って記述した場合には、次のようになります。
const arry = [1, 2, 3, 4, 5];
for( let index = 0; index < arry.length; index++ ){
let value = arry[ index ];
console.log( value, index, arry );
}
アロー関数を使った例
const arry = [1, 2, 3, 4, 5];
arry.forEach( ( value, index, arry) => console.log( value, index, arry ) );
名前付き関数を使った例
const arry = [1, 2, 3, 4, 5]; //名前付き関数としてforEachで使用するコールバック関数を定義
function multiply5( value ) {
console.log( value * 5 );
}
arry.forEach( multiply5 ); //名前付き関数をコールバック関数として渡す
>5
>10
>15
>20
>25
map:新しい配列の作成
mapメソッドは、コールバック関数の戻り値を要素に取る新しい配列を返します。
構文:mapの記法
let 新しい配列 = 配列.map( ( value, index, arry) => {
return 新しい配列に追加したい値;
} [, _this]);
mapメソッドの使い方は基本的にはforEachメソッドと同じですが、mapは戻り値として新しい配列を返す点が異なります。
元の配列の数値に5を掛けた値を保持する配列を作成
const arry = [1, 2, 3, 4, 5];
function multiply5( value ) {
console.log( value * 5 );
}
const newArry = arry.map(multiply5); //新しい配列を返す
// const newArry = arry.map( value => value *5 );と同じ意味
console.log( newArry );
>[5, 10, 15, 20, 25]
filter:特定の値を除いた新しい配列の作成
filterメソッドは、コールバック関数の条件がtrueになったときの配列の要素のみを保持する新しい配列を作成します。
構文:filterの記法
let 新しい配列 = 配列.filter( ( value, index, arry) => {
return 真偽値; //trueのときのvalueが新しい配列に追加される。
} [, _this]);
mapメソッドの使い方は基本的にはforEachメソッドと同じですが、mapは戻り値として新しい配列を返す点が異なります。
3より大きい数値のみ保持する配列の作成
const arry = [1, 2, 3, 4, 5];
function gt3( value ) {
return value > 3;
}
const newArry = arry.filter(gt3);
console.log( newArry );
>[4, 5]
every:すべての要素の値が条件に一致するか
everyメソッドは、すべての要素がコールバック関数で実装された条件でtrueとなるかどうかをテストします。すべての条件が一致した場合には結果がtrueになり、それ以外はfalseになります。
構文:everyの記法
let 結果 = 配列.every( ( value, index, arry) => {
return 真偽値;
} [, _this]);
すべての要素が条件に一致するか確認
const arry = [1, 2, 3, 4, 5];
const result1 = arry.every( value => value > 0 ); //すべての要素が0より大きいか
console.log( result1 );
>true
const result2 = arry.every( value => value > 3 ); //すべての要素が3より大きいか
console.log( result2 );
>false
some:少なくとも1つの値が条件に一致するか
someメソッドは、少なくとも1つの値がコールバック関数で実装された条件でtrueとなるかどうかをテストします。1つも条件に一致しない場合には結果がfalseになり、それ以外はtrueになります。
構文:someの記法
let 結果 = 配列.some( ( value, index, arry) => {
return 真偽値;
} [, _this]);
少なくとも1つ条件に一致するか確認
const arry = [1, 2, 3, 4, 5];
const result1 = arry.some( value => value > 4);
console.log( result1 );
>true
find:条件を満たした最初の要素の値を取得
findメソッドは、コールバック関数の条件を満たした最初の値を返します。
構文:findの記法
let 条件を満たす最初の値 = 配列.find( ( value, index, arry) => {
return 真偽値;
} [, _this]);
2より大きい最初の値を取得
const arry = [1, 2, 3, 4, 5];
const result1 = arry.find( value => value > 2);
console.log( result1 );
>3
sort:配列を並べ替え
sortメソッドは、要素の順番を並べ変えることができます。
構文:sortの記法
文字列として昇順で要素を並べ替え
配列.sort();
比較関数を使って要素を並べ替え
配列.sort( 比較関数 );
昇順にする場合
const arry = [ "b", "c", "a" ];
strArry.sort();
console.log( strArry);
> [ "a", "b", "c" ]
sortを使って要素を並べ替える場合には、要素の値は文字列として扱われます。数値として並べ替える場合には、比較関数を使います(比較関数とは、ソートの機能を定義する関数のことです)。
function compare(val1, val2){ //比較関数には2つの引数が渡ってくる
if ( val1 < val2 ){
return -1; //戻り値が0より小さい場合、val1をval2の前に配置
}
if ( val1 > val2 ){
return 1; //戻り値が0より大きい場合、val2をval1の前に配置
}
return 0; //戻り値が0の場合、val1、val2の順番をそのまま維持
}
const arry = [ 10, 2, 7, 3, 9 ];
arry.sort( compare );
console.log( arry );
> [ 2, 3, 7, 9, 10 ]
比較関数は、2つの引数を取ります。このとき、引数として渡される値は、配列が保持する値の中でランダムに選択されたものです(実際は、ブラウザが使っているソートアルゴリズムの挙動によります)。ここで、開発者が行うべきことは、「渡された2つの値を比べて、どちらの値を配列の前の要素に配置したいのかを、戻り値でソートアルゴリズムに伝える」ことです。
上記のコードのように、戻り値として0、負の値、正の値を返すことによって、ソートアルゴリズムに対して2つの値のどちらを前に持ってくるかを指示できます。ソートアルゴリズムは、このような比較を、値を変えて何回も繰り返し行うことで、少しずつ配列の要素をソートしていきます。
単純に数字の並べ替えを行う場合は、次の記述を使用します。
const arry = [ 10, 2, 7, 3, 9 ];
//昇順(小さい数値から大きい数値へ並べ替え)
function ascending( a , b ){
return a - b;
}
console.log( arry.sort( ascending ) );
>[ 2, 3, 7, 9, 10 ]
const arry = [ 10, 2, 7, 3, 9 ];
//降順(大きい数値から小さい数値への並べ替え)
function descending( a , b ){
return b -a ;
}
console.log( arry.sort( descending) );
>[ 10, 9, 7, 3, 2]
ascendingとdescendingは、数値を昇順、降順がソートするときに使うことができる記述方法です。ここでやっていることは、戻り値として0、負の値、正の値のいずれかを返すことで、2つの値のどちらかを前に持ってくるか決定しているだけです。
reduce:配列から単一の出力値を生成
reduceメソッドは、配列をループして各要素の値から単一の出力値を生成します。
構文:reduceの記法
let result = 配列.reduce( ( totalValue, currentValue, index, arry ) => {
return nextTotalValue;
} [, initValue] );
- totalValue:前のループの戻り値(nextTotalValue)が渡されます。初回ループのときはinitValueの値(initValueが設定されていた場合)、または配列の1つ目の要素の値が渡されます。
- currentValue:配列の要素が1つずつ渡されていきます。初回のループのときは、配列の1つ目の要素の値(initValueが設定されていた場合)、または配列の2つ目の要素の値が渡されます。
- index :配列のインデックスが1つずつ渡されてきます。
- arry :配列自体が渡されます。
- nextTotalValue:次のループのtotalValueに設定したい値を設定します。また、最後のループの戻り値がreduceメソッドの結果(result)となります。
- result :最後のループの戻り値となります。
- initValue:設定された場合、1ループ目のtotalValueに設定されます。
reducerを使った配列の要素を加算
function reducer( totalValue, currentValue ){
return totalValue + currentValue;
}
const arry = [1, 2, 3, 4, 5];
const result = arry.reduce( reducer );
console.log( result );
>15
reduceメソッドに渡すコールバック関数の処理は、次のようになります(reduceメソッドに渡すコールバック関数はreducerと呼びます)。
1回目のループ
1回目のループでは、totalValueに対して、配列の最初の要素の値(1)が渡されます。そして、配列の2番目の要素の値(2)がcurrentValueに渡されます。なお、reduceメソッドの第2引数が設定されている場合には、その値がtotalValueに渡され、最初の値がcurrentValueに渡されます。そして、reducerの戻り値が次のループのtotalValueの値となります。
2回目のループ
2回目のループでは、1ループ目のreducerの戻り値がtotalValueに渡されます。一方、currentValueには、まだ処理されていない次の要素の値(3)が渡されます。以降、配列のすべての要素がcuurentValueに渡されるまで、同様の処理を繰り返します。
最後のループ
配列のすべての要素をすべて処理し終わった時点でreducerが返す戻り値が、reduceメソッドの戻り値となります。