JavaScript | 関数はオブジェクト

JavaScript JavaScript
スポンサーリンク

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

ポイント

  • sumadd と同じ関数オブジェクトを指しているので実行できます。
  • 名前付き関数を別の値で上書きできるのは「関数も変数扱いできる」から。

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 が最初に関数オブジェクトを参照しているため、saynull にしても 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() に直接渡せる。


練習問題

  1. 関数 square を作り、それを f に代入して実行してみる。
  2. 関数 operate(a, b, op) を作る。op は関数で、op(a,b) の結果を返す。addmul を渡して動作を確認する。
  3. 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
JavaScript
function 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
JavaScript
function 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 のような一歩進んだ使い方へ進むと応用が広がります。
タイトルとURLをコピーしました