HOWTO · JavaScript
JavaScript 関数をパラメーターとして渡す
JavaScriptでは、`greet`のように関数参照を渡すと、受け取る側に関数そのものを渡せます。一方、`greet()`と書くと関数がその場で実行され、関数ではなく戻り値が渡されます。
このページの内容
JavaScriptで関数を渡すには、greetのように関数を呼び出さず、その参照を受け取り側の関数に渡します。greet()と書くと、その場で関数が実行され、代わりに戻り値が渡されます。受け取った関数を呼び出すかどうか、いつ呼び出すかは、受け取り側の関数が決めます。渡された関数は、コールバック関数と呼ばれることもあります。この仕組みを使うと、別の関数が利用する処理を渡せます。
名前付き関数を引数として渡す
処理を個別に定義したり、再利用したりする場合は、名前付き関数が便利です。この例では、formatGreetingが関数greetと名前を受け取り、受け取った関数にその名前を渡して呼び出します。
function greet(name) {
return "Hello, " + name + "!";
}
function formatGreeting(callback, name) {
return callback(name);
}
const message = formatGreeting(greet, "Mina");
console.log(message);
formatGreeting(greet, "Mina")という呼び出しでは、関数参照greetと文字列"Mina"の2つの値を渡しています。受け取り側の関数内でcallback(name)を呼び出すと、greetが実行され、その結果が返されます。formatGreeting(greet("Mina"), "Mina")と書いた場合は、formatGreetingが始まる前にJavaScriptがgreetを呼び出すため、最初の引数には関数ではなく文字列が渡されます。
関数をほかの引数と一緒に渡す
関数には、通常の値と複数のコールバック関数を一緒に渡せます。受け取り側の関数は、どのコールバックを呼び出すか、どの値を渡すかを選べます。この例では、applyOperationが数値と2つの関数を受け取り、それぞれの関数を数値に適用します。
function applyOperation(value, first, second) {
return [first(value), second(value)];
}
function double(number) {
return number * 2;
}
function addThree(number) {
return number + 3;
}
const results = applyOperation(4, double, addThree);
console.log(results.join(", "));
引数の順序は重要です。applyOperationの各パラメーターには、呼び出し時と同じ順序で値が渡されます。valueには4、firstにはdouble、secondにはaddThreeが渡されます。この関数は、計算した2つの値を配列で返します。APIにコールバックとオプションやデータを渡す場合も同じ考え方です。パラメーターの順序を確認し、関数を実行せず名前で渡してください。
無名関数とアロー関数をコールバックとして使う
呼び出す場所で一度だけ使う処理なら、名前付き関数を別に宣言せず、その場で定義できます。次の例では、最初のmap呼び出しに無名関数を渡し、2回目のmap呼び出しにはアロー関数を渡します。
const numbers = [1, 2, 3];
const doubled = numbers.map(function (number) {
return number * 2;
});
const tripled = numbers.map((number) => number * 3);
console.log(doubled.join(", "));
console.log(tripled.join(", "));
この例の計算結果は、doubled.join(", ")が2, 4, 6、tripled.join(", ")が3, 6, 9です。これはコードの動作から導ける値であり、ここで実行した結果ではありません。
2, 4, 6
3, 6, 9
mapは配列の各要素に対してコールバックを呼び出し、戻り値から新しい配列を作ります。コールバックに名前を付ける必要はありません。無名関数はfunctionキーワードを使い、アロー関数は=>と、値が暗黙に返される式本体を使います。処理が分かりやすくなる形式を選んでください。アロー関数のthisは、外側のスコープから引き継がれます。コールバック自身のthisが必要な場合は、通常の関数を使い、呼び出し元のAPIが定めるthisの動作を確認してください。
関数から別の関数を返す
関数は別の関数を返すこともできます。コールバックを引数として渡す場合とは異なり、外側の関数を呼び出すと関数が作られて返されるため、保存して後から呼び出せます。たとえば、makeMultiplierは選んだ乗数を周囲のスコープに保持する関数を返します。
function makeMultiplier(multiplier) {
return function (number) {
return number * multiplier;
};
}
const triple = makeMultiplier(3);
console.log(triple(5));
makeMultiplier(3)は関数を返すので、tripleはその返された関数を参照します。次にtriple(5)を呼び出すと、その関数にnumber引数が渡されます。内側の関数は、それを作成した呼び出しのmultiplierにも引き続きアクセスできます。このように外側のスコープへのアクセスが保たれる仕組みをクロージャと呼びます。高階関数とは、別の関数を受け取る関数、関数を返す関数、またはその両方を行う関数です。
よくある質問
複数の関数を渡すにはどうすればよいですか? 関数参照をそれぞれ別の引数位置に置き、コンマで区切ります。受け取り側の関数のパラメーターと同じ順序にしてください。
コールバックはいつ実行されますか? 呼び出すタイミングは受け取り側の関数が決めます。関数を渡しただけでは実行されません。受け取り側の設計に応じて、すぐに、後で、または複数回呼び出されることがあります。
関数から別の関数を返せますか? はい。外側の関数を呼び出して返された関数を受け取り、必要に応じて呼び出すか、別の場所に渡します。クロージャに設定値を保持させた関数を作るときによく使われます。