JavaScriptでは「関数もオブジェクト」です。これは最初はちょっと不思議ですが、要するに「関数は値(オブジェクト)として扱える」ということ。変数に入れられるし、引数に渡せるし、プロパティだって持てます。以下で段階を追って、実例を動かしながら理解していきましょう。
1. 基本:名前付き関数(関数宣言)
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
console.log(typeof add); // "function"
JavaScriptポイント
addは「関数の名前」ですが、内部的にはaddという変数に関数(オブジェクト)が入っているイメージです。typeof addは"function"と出ますが、実際は「呼べるオブジェクト」です。
2. 関数を変数に代入(関数は値)
let sum = add; // 関数オブジェクトを別の変数に代入
console.log(sum(2,3)); // 5
// 関数自体を上書きもできる(実務では慎重に)
add = "hello";
console.log(add); // "hello"
JavaScriptポイント
sumもaddと同じ関数オブジェクトを指しているので実行できます。- 名前付き関数を別の値で上書きできるのは「関数も変数扱いできる」から。
3. 無名関数(関数リテラル)を変数に代入
let multiply = function(x, y) {
return x * y;
};
console.log(multiply(4, 5)); // 20
console.log(multiply); // function (x, y) { ... }
JavaScriptポイント
- 関数に名前を付けずに(無名で)そのまま変数に格納するパターン。
- この形はコールバックや一時的な関数に便利。
4. 関数を引数に渡す(コールバック)
function greet(name, formatter) {
// formatter は関数として扱える
console.log("Hello, " + formatter(name));
}
function upper(s) { return s.toUpperCase(); }
greet("Hanako", upper); // Hello, HANAKO
// 無名関数でも渡せる
greet("Taro", function(n) { return "Mr. " + n; }); // Hello, Mr. Taro
JavaScriptポイント
- 関数を「引数」として渡せることで、処理を柔軟に差し替えられます(典型的な設計パターン)。
5. 関数を返す(高階関数)
function makeAdder(x) {
return function(y) {
return x + y;
};
}
let add10 = makeAdder(10);
console.log(add10(5)); // 15
JavaScriptポイント
- 関数が別の関数を返すこともできます。これが「クロージャ」の入り口です(
xを覚えている関数が返る)。
6. 関数にもプロパティをつけられる(オブジェクトと同様)
function counter() { return counter.count++; }
counter.count = 1;
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter.count); // 3
JavaScriptポイント
- 関数はオブジェクトなのでプロパティ(
counter.count)を付けられます。ただし設計上はあまり多用しない方が読みやすいコードになります。
7. アロー関数(短い書き方)
const sub = (a, b) => a - b;
console.log(sub(10,3)); // 7
JavaScriptポイント
- アロー関数は関数リテラルの短縮形。
thisの扱いが通常の関数と違うので注意(まずは「短く書ける」利点を覚えよう)。
例題 1 — 別名で呼ぶ
問題:以下のコードの出力は?
function say() { return "OK"; }
const alias = say;
say = null;
console.log(alias());
JavaScript答え:"OK"
理由:alias が最初に関数オブジェクトを参照しているため、say を null にしても alias() は問題なく動く。
例題 2 — 関数を引数にして処理を変える
作るもの:配列の各要素に関数を適用する applyToAll を作る。
function applyToAll(arr, fn) {
let result = [];
for (let i = 0; i < arr.length; i++) {
result.push(fn(arr[i]));
}
return result;
}
console.log(applyToAll([1,2,3], function(n){ return n * 2; })); // [2,4,6]
JavaScript解説:fn は関数なので、呼び出し方を変えれば動作が変わる(汎用性が高い)。
例題 3 — 関数を返す(カスタムフィルタ)
作るもの:ある閾値より大きいかチェックする関数を作る関数 greaterThan(th)。
function greaterThan(th) {
return function(x) {
return x > th;
};
}
const gt5 = greaterThan(5);
console.log([3,6,8,2].filter(gt5)); // [6,8]
JavaScript解説:greaterThan は「条件関数」を返すので、.filter() に直接渡せる。
練習問題
- 関数
squareを作り、それをfに代入して実行してみる。 - 関数
operate(a, b, op)を作る。opは関数で、op(a,b)の結果を返す。addとmulを渡して動作を確認する。 makeMultiplier(n)を作り、戻り値は「引数を n 倍する関数」にする。makeMultiplier(3)を使って[1,2,3]を変換する。
(解答は最後に載せます)
実務っぽい使いどころ(初心者が知っておくと役に立つ場面)
- コールバック:非同期処理(タイマーやAPI呼び出し)の結果を受け取るときに関数を渡す。
- 高階関数:配列操作(
.map,.filter,.reduce)では関数を渡してデータを整形する。 - 設定可能な処理:ライブラリやユーティリティで「動作を差し替えられる」仕組みを作るときに便利。
- クロージャ:状態を閉じ込めた関数を作れば、カプセル化に役立つ(例:簡易モジュールやプライベート変数の代替)。
練習問題の解答(先ほどの3問)
function square(x) { return x * x; }
let f = square;
console.log(f(4)); // 16
JavaScriptfunction operate(a, b, op) { return op(a, b); }
function add(a,b){return a+b;}
function mul(a,b){return a*b;}
console.log(operate(2,3,add)); // 5
console.log(operate(2,3,mul)); // 6
JavaScriptfunction makeMultiplier(n){
return function(x){
return x * n;
};
}
const triple = makeMultiplier(3);
console.log([1,2,3].map(triple)); // [3,6,9]
JavaScript最後に(学習のコツ)
- まずは「関数を変数に入れる」「関数を渡す」「関数を返す」の3つを手でたくさん試す。
- コンソール(ブラウザの DevTools)で
console.logを多用して、どの変数が何を参照しているか確認する。 - 次に「アロー関数」や
.map/.filterのような一歩進んだ使い方へ進むと応用が広がります。
