169
144

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScript 高階関数を説明するよ

Last updated at Posted at 2017-04-17

なんとなく使っていた高階関数を言語化してみました。

##高階関数とは
高階関数を一言で表すと、**「関数を引数、戻り値として扱う関数」**のことです。

これにはJavaScriptの関数はデータ型の一種という前提があります。
JavaScriptでは関数そのものを他の数値型や文字列型などと同様に関数の引数として渡したり、戻り値として返したりすることができるのです。つまり関数を引数で扱うのが高階関数になります。

...言葉だけでは分かりにくいですね。

実際に高階関数をつかったコードを書いてみます。

script.js
//高階関数higherOrderFunctionsを定義する
function higherOrderFunctions(data,f){
 for(var key in data){
  f(data[key],key);
 }
}

//ユーザー定義関数(高階関数の引数となる関数)を定義する
function userFunction(value ,key){
 console.log(key + ':' + value);
}

//実行
var array = [5,6,7,8,9,10 ];
higherOrderFunctions(array,userFunction);//0:5 1:6  2:7  3:8  4:9  5:10
//第一引数に処理する配列
//第二引数に配列を処理するユーザー定義関数(高階関数の引数となる関数)

*Higher-order Functionsというのは高階関数の英語

順を追って説明します。

はじめに、高階関数を定義しています。
fの部分に高階関数の引数となる関数が設定されています。
この高階関数はfor...in文によってdata(配列)の個々の要素をひとつひとつ関数fに渡す処理になっています。

次に、高階関数の引数となる関数、ユーザー定義関数を定義します。
ここではひとつ上の関数(高階関数)から渡されたvalue ,keyを処理するコードが書かれています。

最後に高階関数の引数に処理する配列と使用する関数を設定することで結果が出力されます。

かんたんにまとめると下記の流れになります。

  1. 高階関数のfor...in文で配列のキーと値を引数である関数fに渡す(渡す担当)
  2. fに指定されたユーザー定義関数でキーと値をリストの形式に処理して出力する(処理担当)

*上記のユーザー定義関数はコールバック関数とも呼ばれます。
あとで呼び出される(コールバックされる)べき処理、という意味の関数です。

高階関数ではユーザー定義関数を自由に置き換えることができます。
例では配列の内容をリスト形式で表示しましたが、fに設定する関数を配列内の数値を合計する処理に変更することもできるのです。(高階関数は渡し方を担当するだけだからですね)

以上が基本的な高階関数の説明になります。

##代表的な高階関数 
代表的な高階関数の例としてArrayオブジェクトのforEach, map, filter, sort, reduceといったメソッドがあります。

###forEach
array.forEach(callback[,that])
 array: 配列
 callback: 配列の個々の要素を処理するための関数
 that: callbackの中でthisが示すオブジェクト

script.js
var data = [5,6,7,8];
data.forEach(function(value,index,array){
  console.log(value * value);//25 , 36, 49, 64
});

forEachは、配列の要素を順番に取り出してcallback関数に渡す高階関数。
第一引数は要素の値
第二引数はインデックス番号
第三引数は元の配列
が指定される。第二、第三引数を利用しない場合は省略可。

###map
array.map(callback[,that])
 array: 配列
 callback: 配列の個々の要素を加工するための関数
 that: callbackの中でthisが示すオブジェクト

script.js
var data = [5,6,7,8];
var result = data.map(function(value,index,array){
  return value * value;
});
console.log(result);;//[25, 36, 49, 64]

mapは、配列の要素を順番に取り出してcallback関数に渡し,戻り値として加工した結果を返す高階関数。
(callback関数への値の渡し方はforEachと一緒。返し方が違う)

mapforEachと比較するとわかりやすいですね。
forEachはcallback関数で処理をするのでそのままconsole.logで出力していますが、
mapは戻り値として加工した結果を新しく返すので、別にconsole.logで出力しています。出力結果が[25, 36, 49, 64]と配列であることに注目してください。

###filter
array.filter(callback[,that])
 array: 配列
 callback: 配列の個々の要素を判定するための関数
 that: callbackの中でthisが示すオブジェクト

script.js
var data = [5,6,7,8];
var result = data.filter(function(value,index,array){
  return value <= 6;
});
console.log(result);//[5, 6]

filterは、指定されたcallback関数で個々の要素を判定し、条件に合致した要素だけを取り出す高階関数。
callback関数(この場合、value <= 6)がtrueを返した値だけ、配列に書き戻すのがfilterの役割。

###sort
array.sort(callback[,that])
 array: 配列
 callback: 配列の要素を並び替えるための関数
 that: callbackの中でthisが示すオブジェクト

script.js
var data = [5,8,7,6];
var result = data.sort(function(a,b){
  return a - b;//昇順
});
console.log(result);[5, 6, 7, 8]

var result = data.sort(function(a,b){
  return  b - a;//降順
});
console.log(result);[8, 7, 6, 5]

sortデフォルトで配列を文字列として辞書順に並び替える高階関数。
引数の設定を変えることで並べ方を変えることができます。
・引数は2つ(比較する配列要素)
・第一引数が第二引数より小さい場合は負数、大きい場合は正数を返す

###reduce
array.reduce(callback[,init])
 array: 配列
 callback: 配列の要素を左から右へ処理するための関数
 init: 初期値

var data = [5,6,7,8];
var result = data.reduce(function(a,b){
  return a + b;
});
console.log(result);//26

reduceは、隣同士の2つの要素を左から右へcallback関数で処理してひとつの値にするための高階関数。

上記の場合、要素の左から順に
5+6で11
11+7で18
18+8で26
26が返ってくる。

右から左へ処理したい場合はreduceRightという高階関数が用意されている。

他にもArrayオブジェクトにはevery, some, find, findIndexといったメソッドが用意されています。

##まとめ
高階関数は**「関数を引数、戻り値として扱う関数」**のこと。
高階関数はcallback関数への要素の渡し方を担当
callback関数が処理方法を担当

ありがとうございました。

169
144
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
169
144

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?