JavaScript | 関数はオブジェクト

JavaScript JavaScript
スポンサーリンク

関数は「値のひとつ」だと考える

はじめの一歩として、「関数も数値や文字列と同じように“値”として扱える」と覚えてください。関数は“動くレシピ”のようなもの。レシピを箱(変数)に入れたり、人に渡したり、別のレシピに差し替えたりできます。これが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) を作り、addmultiply を渡して試す。
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つのボタン「足す」「引く」を作り、クリック時に異なる関数を渡して同じ表示関数で結果を出す。

まとめ

  • 関数は値: 変数に入る、渡せる、返せる。柔軟さの鍵。
  • 無名関数・アロー関数: その場で短い処理を書くのに便利。
  • コールバック: 「何をするか」を渡す設計で、再利用性・拡張性が上がる。
タイトルとURLをコピーしました