JavaScript | 基礎構文:関数 – 関数式

JavaScript JavaScript
スポンサーリンク

関数式って何者?

関数式は、
「関数そのものを“値”として扱い、変数に代入したり、他の関数に渡したりする書き方」 です。

これだけだと少し抽象的なので、
まずは「関数宣言」との違いから見ていきます。


関数宣言との違いから理解する

関数宣言(おさらい)

関数宣言はこういう書き方でした。

function greet(name) {
  console.log("こんにちは、" + name + "さん");
}

greet("太郎");
JavaScript

ここでは、greet という名前の関数を「宣言」しています。
この書き方の特徴は、
スクリプトのどこからでも(同じスコープ内なら)呼び出せる ことです。

greet("前から呼んでもOK");

function greet(name) {
  console.log("こんにちは、" + name + "さん");
}
JavaScript

こう書いても動きます。
これは「関数宣言がホイスティングされる(上に持ち上げられる)」からです。

関数式の基本形

関数式はこう書きます。

const greet = function (name) {
  console.log("こんにちは、" + name + "さん");
};

greet("太郎");
JavaScript

function (name) { ... } という“無名の関数”を、
greet という変数に代入しています。

ここが重要です。
関数式は「関数を作る」と同時に、「それを変数に代入している」 という点がポイントです。

そして、関数式はホイスティングされません。

greet("これはエラーになる");

const greet = function (name) {
  console.log("こんにちは、" + name + "さん");
};
JavaScript

このコードはエラーになります。
greet が定義される前に呼び出しているからです。

関数式は「その行に到達したとき」に初めて代入される、
という感覚を持っておいてください。


関数式の「おいしいところ」

関数を“値”として扱いやすい

関数式の一番の強みは、
関数を「値」として自然に扱えること です。

例えば、こんなことができます。

変数に代入して使う

const add = function (a, b) {
  return a + b;
};

console.log(add(2, 3)); // 5
JavaScript

配列に入れる

const funcs = [
  function () { console.log("一つ目"); },
  function () { console.log("二つ目"); },
];

funcs[0](); // 一つ目
funcs[1](); // 二つ目
JavaScript

他の関数に渡す

function runTwice(fn) {
  fn();
  fn();
}

const hello = function () {
  console.log("こんにちは");
};

runTwice(hello);
// こんにちは
// こんにちは
JavaScript

ここが重要です。
関数式を使うと、「関数を変数に入れる」「関数を引数として渡す」「関数を戻り値として返す」が自然にできる。
これが“関数を第一級の値として扱う”という JavaScript の強みです。


無名関数と名前付き関数式

無名関数の関数式

さっきの例は「無名関数(名前なし)」でした。

const greet = function (name) {
  console.log("こんにちは、" + name + "さん");
};
JavaScript

この場合、関数自体には名前がありません。
greet という変数名でアクセスします。

名前付き関数式

実は、関数式にも名前をつけることができます。

const greet = function greetInner(name) {
  console.log("こんにちは、" + name + "さん");
};
JavaScript

このとき、

外からは greet() として呼び出す
関数の中からは greetInner() という名前で自分自身を呼べる

というメリットがあります。

例えば、再帰関数を書くときに使えます。

const factorial = function fact(n) {
  if (n === 0) return 1;
  return n * fact(n - 1);
};

console.log(factorial(5)); // 120
JavaScript

ただし、初心者のうちは
「関数式=無名関数を変数に代入するもの」
と覚えておけば十分です。


関数式とアロー関数の関係

実はアロー関数も「関数式」の一種

アロー関数も、形を変えただけで本質は関数式です。

const greet = (name) => {
  console.log("こんにちは、" + name + "さん");
};
JavaScript

これは、

const greet = function (name) {
  console.log("こんにちは、" + name + "さん");
};
JavaScript

とほぼ同じ意味です(this の扱いなど細かい違いはありますが、今は置いておいてOK)。

つまり、

「function を使った関数式」
「=> を使った関数式(アロー関数)」

という2種類がある、と捉えるとスッキリします。


実務で関数式がよく使われる場面

コールバックとして渡すとき

イベントリスナーなどで、よくこう書きます。

button.addEventListener("click", function () {
  console.log("クリックされました");
});
JavaScript

ここで function () { ... } は、
まさに「関数式」です。

アロー関数で書くとこう。

button.addEventListener("click", () => {
  console.log("クリックされました");
});
JavaScript

「イベントが起きたときに実行する処理」を、
その場で関数式として定義して渡しているわけです。

配列操作(map, filter, forEach など)

配列メソッドでも、関数式は大活躍します。

const numbers = [1, 2, 3];

const doubled = numbers.map(function (n) {
  return n * 2;
});

console.log(doubled); // [2, 4, 6]
JavaScript

アロー関数ならこう。

const doubled = numbers.map((n) => n * 2);
JavaScript

ここが重要です。
「何かを“後で実行する処理”として渡したいとき、
その場で関数式を書く」というパターンが、実務ではめちゃくちゃ多い。


初心者として押さえておきたい「関数式の感覚」

「関数も値」という感覚を持つ

関数式を理解するうえで一番大事なのは、
「関数も数値や文字列と同じ“値”として扱える」
という感覚です。

数値を変数に入れる:

const x = 10;
JavaScript

関数を変数に入れる:

const fn = function () {
  console.log("関数です");
};
JavaScript

どちらも「何かを変数に代入している」だけです。
違うのは、その「何か」が数値か関数か、というだけ。

この感覚が腑に落ちると、
「関数を引数に渡す」「関数を返す」といった書き方が
一気に自然に感じられるようになります。


まとめ:関数式で本当に押さえてほしいこと

関数式は、

const 名前 = function (引数) {
  // 処理
};
JavaScript

という形で書く「関数を値として扱うための書き方」。

関数宣言との主な違いは、

ホイスティングされない(定義より前では使えない)
変数に代入する前提なので、「関数を値として扱う」場面に強い

実務では、

イベントリスナー
配列メソッド(map, filter, forEach など)
コールバックや非同期処理のハンドラ

などで、ほぼ必ず関数式(またはアロー関数)が登場します。

もし今、

function greet() { ... }
JavaScript

には慣れてきたなら、
次の一歩として、

const greet = function () { ... };
const greet = () => { ... };
JavaScript

という「関数式の形」にも慣れていくと、
書けるコードの幅が一気に広がります。

タイトルとURLをコピーしました