関数とは?

JavaScriptの関数とは、複数の処理をひとまとまりにし、必要なときに呼び出して実行できる仕組みです。
関数を使うことで、同じ処理を何度も書く必要がなくなり、コードの再利用性や可読性、保守性を高めることができます。
JavaScriptで関数を定義する主な方法には、次の3つがあります。
- 関数宣言
- 関数式
- アロー関数
関数宣言とは?
関数宣言は、functionキーワードの後ろに関数名を記述して定義する方法です。
function greet() {
console.log("Hello, World!");
}
greet();
実行結果は次のとおりです。
Hello, World!
この例では、greetという関数を定義し、greet()で呼び出しています。
関数宣言はホイスティングの対象となるため、同じスコープ内であれば、宣言より前に呼び出すこともできます。
関数式とは?
関数式は、関数を値として作成し、変数へ代入する定義方法です。
const greet = function () {
console.log("Hello, World!");
};
greet();
実行結果は次のとおりです。
Hello, World!
この例では、名前を持たない関数を作成し、greetという変数へ代入しています。このような名前のない関数を無名関数と呼びます。
関数式は、変数への代入が完了した後で呼び出す必要があります。
関数宣言のホイスティング
ホイスティングとは、JavaScriptエンジンがコードを実行する前に、変数や関数の宣言をそのスコープ内で事前に処理する仕組みです。
関数宣言では、関数名だけでなく関数本体も事前に利用可能な状態になるため、宣言より前に呼び出せます。
greet();
function greet() {
console.log("Hello, World!");
}
このコードは正常に動作し、次の結果を出力します。
Hello, World!
ただし、実際にソースコードの位置が上へ移動しているわけではありません。JavaScriptエンジンが実行前に関数宣言を登録しているため、このような動作になります。
関数式とホイスティング
「関数式はホイスティングされない」と説明されることがありますが、より正確には、関数を代入する変数宣言の方法に応じて挙動が決まります。
constを使った関数式
greet();
const greet = function () {
console.log("Hello, World!");
};
constで宣言した変数は、宣言より前ではTemporal Dead Zoneにあるため、ReferenceErrorが発生します。
ReferenceError: Cannot access 'greet' before initialization
varを使った関数式
greet();
var greet = function () {
console.log("Hello, World!");
};
varの宣言は事前に処理され、undefinedで初期化されます。しかし、関数の代入はまだ行われていないため、undefinedを関数として呼び出そうとしてTypeErrorが発生します。
TypeError: greet is not a function
名前付き関数式とは?
関数式では、無名関数だけでなく、関数自体に名前を付けることもできます。これを名前付き関数式と呼びます。
const greet = function showGreeting() {
console.log("Hello, World!");
};
greet();
外部から関数を呼び出すときは、変数名のgreetを使用します。
関数に名前を付けると、エラー発生時のスタックトレースに関数名が表示されやすくなり、デバッグに役立つことがあります。
アロー関数とは?
ES6以降では、関数式をより短く記述できるアロー関数も広く利用されています。
const greet = () => {
console.log("Hello, World!");
};
greet();
処理が1つの式だけである場合は、さらに短く記述できます。
const add = (a, b) => a + b;
console.log(add(3, 5)); // 8
アロー関数も変数へ代入する関数式の一種なので、変数が初期化された後で呼び出す必要があります。
また、アロー関数は通常の関数と異なり、独自のthisやargumentsを持ちません。そのため、オブジェクトのメソッドやコンストラクタとして使用する場合は注意が必要です。
関数宣言と関数式の比較
| 項目 | 関数宣言 | 関数式 |
|---|---|---|
| 基本構文 | function greet() {} |
const greet = function () {}; |
| 関数名 | 必須 | 無名関数または名前付き関数を代入できる |
| 宣言前の呼び出し | 可能 | 原則として不可 |
| ホイスティング | 関数本体まで事前に利用可能になる | 代入先の変数宣言に従う |
| 主な用途 | 独立した処理を分かりやすく定義する | 変数への代入、引数、戻り値として利用する |
関数式が役立つ場面
関数式は、関数を値として扱いたい場面で便利です。
コールバック関数として渡す
const numbers = [1, 2, 3];
numbers.forEach(function (number) {
console.log(number);
});
forEach()へ関数式を引数として渡し、配列の各要素を処理しています。
条件に応じて関数を切り替える
const isJapanese = true;
const greet = isJapanese
? function () {
console.log("こんにちは");
}
: function () {
console.log("Hello");
};
greet();
関数式は値として扱えるため、条件に応じて変数へ代入する関数を切り替えることもできます。
関数を定義するときの注意点
- 関数宣言は宣言前でも呼び出せるが、コードの流れを分かりやすくするため、定義後に呼び出す構成も検討する。
- 関数式やアロー関数は、変数へ代入した後で呼び出す。
- 再代入しない関数式には、基本的に
constを使用する。 - 複雑な処理には、内容が分かる関数名を付ける。
- アロー関数と通常の関数では、
thisの扱いが異なる点に注意する。
まとめ
- 関数は、複数の処理をまとめて再利用するための仕組みである。
- 関数宣言は、
function 関数名()の形式で定義する。 - 関数式は、関数を変数へ代入して定義する。
- 関数宣言はホイスティングにより、宣言前でも呼び出せる。
- 関数式の挙動は、
var、let、constなど、代入先の変数宣言に従う。 constを使った関数式は、初期化前に呼び出すとReferenceErrorになる。- アロー関数は関数式を簡潔に記述できるが、通常の関数とは
thisの扱いが異なる。 - 関数宣言と関数式は、用途やコードの構成に応じて使い分ける。