関数は「値のひとつ」だと考える
はじめの一歩として、「関数も数値や文字列と同じように“値”として扱える」と覚えてください。関数は“動くレシピ”のようなもの。レシピを箱(変数)に入れたり、人に渡したり、別のレシピに差し替えたりできます。これがJavaScriptの柔軟さの源です。
関数を変数に入れて使う
関数はオブジェクトなので、変数に代入して呼び出せます。関数名そのものも「関数オブジェクトが入った変数」です。
function add(x, y) {
return x + y;
}
// 関数を別の変数にコピー
let myAdd = add;
console.log(add(3, 4)); // 7
console.log(myAdd(3, 4)); // 7(同じ関数を呼んでいる)
JavaScript- ポイント: 関数名は“ラベル”。ラベルが違っても、中身の関数が同じなら結果は同じになります。
関数名はただの変数(だから置き換えられる)
関数名も変数なので、別の値を入れ直せます。通常の開発ではめったにしませんが、「関数も値」という感覚を掴むのに役立ちます。
function greet() {
return "Hello!";
}
console.log(greet()); // "Hello!"
// 関数名に文字列を代入(関数じゃなくなる)
greet = "こんにちは";
console.log(greet); // "こんにちは"
// ここで greet() とするとエラー(もう関数じゃないため)
JavaScript- 注意: 実務では関数名を別の型に差し替えるとバグの元。やらないのが基本。
無名関数(匿名関数)をその場で作って入れる
名前をつけずに、直接変数へ関数を入れる書き方です。短い処理を“その場でサッと”作るときに便利。
let multiply = function(x, y) {
return x * y;
};
console.log(multiply(5, 6)); // 30
JavaScript- ポイント: 名前がないので、変数名が“呼び出し名”になります。
- 豆知識: さらに短く書ける「アロー関数」もあります。
let multiply = (x, y) => x * y;
JavaScript関数を引数として渡す(コールバック)
「どう処理するか」を関数で渡せると、同じ枠組みでいろいろな振る舞いを選べます。まさに“レシピを渡す”感覚です。
// 共通の「計算器」:どう計算するかは引数の関数に任せる
function calc(x, y, operation) {
return operation(x, y);
}
// 足し算レシピ
function add(x, y) {
return x + y;
}
// 引き算レシピ
function sub(x, y) {
return x - y;
}
console.log(calc(10, 3, add)); // 13
console.log(calc(10, 3, sub)); // 7
// その場でレシピを渡す(無名関数)
console.log(calc(10, 3, function(a, b) { return a * b; })); // 30
JavaScript- ポイント: 「枠組み(calc)」と「具体的な処理(operation)」を分けると、再利用性が一気に上がります。
よくある実用シーン
ボタンが押されたら実行(イベント処理)
<button id="btn">押すとメッセージ</button>
<script>
const btn = document.getElementById('btn');
btn.addEventListener('click', function() {
alert('押されました!');
});
</script>
JavaScript- ポイント:
addEventListenerは「押されたとき何する?」という関数(コールバック)を受け取ります。
少し待ってから実行(タイマー)
setTimeout(function() {
console.log('2秒後に実行');
}, 2000);
JavaScript- ポイント: 「いつ」「何をするか」を関数で渡す。待機中は関数は“保存”され、時間が来たら“呼ばれる”。
配列の処理(高階関数)
const prices = [100, 200, 300];
// すべて10%割引
const discounted = prices.map(function(p) { return p * 0.9; });
// 200以上だけ抽出
const filtered = prices.filter(function(p) { return p >= 200; });
// 合計を計算
const total = prices.reduce(function(sum, p) { return sum + p; }, 0);
console.log(discounted); // [90, 180, 270]
console.log(filtered); // [200, 300]
console.log(total); // 600
JavaScript- ポイント:
map/filter/reduceは「どう変換・選別・集計するか」を関数で受け取ります。
つまずきやすいポイントと回避策
- 呼び出し忘れ: 関数そのものを渡すときは
doSomething、実行した結果を渡すならdoSomething()。違いを意識する。 - 型の取り違え: 関数名に別の型(文字列・数値)を代入すると、あとで
greet()のように呼べなくなる。避ける。 - thisの扱い: 無名関数とアロー関数では
thisの振る舞いが違う。イベント内で要素を参照したいなら通常の関数を使うのが安全。 - 可読性低下: 無名関数をネストしすぎると読みづらい。短い関数に分け、名前をつけて外に出す。
手を動かす練習問題
- 練習1: 計算器を作る
calculate(x, y, operation)を作り、addとmultiplyを渡して試す。
function calculate(x, y, operation) {
return operation(x, y);
}
function add(a, b) { return a + b; }
function multiply(a, b) { return a * b; }
console.log(calculate(2, 8, add)); // 10
console.log(calculate(2, 8, multiply)); // 16
JavaScript- 練習2: フィルター関数
filterEven(numbers)を作り、偶数だけ返す。判定関数を引数で渡せるよう拡張してみる。
function filter(numbers, predicate) {
const result = [];
for (const n of numbers) {
if (predicate(n)) result.push(n);
}
return result;
}
const nums = [1,2,3,4,5,6];
console.log(filter(nums, n => n % 2 === 0)); // [2,4,6]
console.log(filter(nums, n => n > 3)); // [4,5,6]
JavaScript- 練習3: ボタンで動作を切り替え
- 2つのボタン「足す」「引く」を作り、クリック時に異なる関数を渡して同じ表示関数で結果を出す。
まとめ
- 関数は値: 変数に入る、渡せる、返せる。柔軟さの鍵。
- 無名関数・アロー関数: その場で短い処理を書くのに便利。
- コールバック: 「何をするか」を渡す設計で、再利用性・拡張性が上がる。
