Menu
日本語

JavaScriptの関数宣言|function構文・巻き上げ・return

JavaScriptで関数を宣言する方法をまとめました。functionキーワードの書き方、引数とreturn、巻き上げ(ホイスティング)、関数宣言と関数式の使い分けまで一気に解説します。

関数とは、ひとまとまりの処理に名前をつけたもの

JavaScript でロジックのかたまりに名前をつけて使い回したいときは、必ず関数を書きます。もっとも昔からある素直な書き方が 関数宣言(function declaration) で、function キーワードのあとに関数名を続ける形式です。

index.js
Output
Click Run to see the output here.

これを前から順に読んでいくと、こうなります。

  • function は、関数宣言の始まりを示すキーワード。
  • greet は関数名。
  • (name) は仮引数リスト。関数が受け取る入力です。
  • 波かっこで囲まれたブロックが関数の本体。
  • greet("Ada")呼び出しname"Ada" を束縛した状態で、JavaScript が本体を実行します。

関数は定義しただけでは動きません。呼び出して初めて実行されます。

仮引数と実引数

仮引数(parameter) は関数を定義するときに書く名前で、 実引数(argument) は呼び出すときに渡す値のことです。日常会話ではほぼ同じものとして扱われますが、エラーメッセージを読むときにはこの区別が効いてきます。

index.js
Output
Click Run to see the output here.

ここで baseexponent仮引数(パラメータ)210 は**実引数(アーギュメント)**です。JavaScript は渡された順番どおりに束縛していきます。つまり、1 番目の実引数は 1 番目の仮引数へ、2 番目は 2 番目へ、という具合ですね。

他の言語と違って、JavaScript は引数の数が合わなくても文句を言いません。足りない分は undefined になり、多すぎる分は黙って無視されます。柔軟ではあるものの、ハマりどころにもなりがち。デフォルト引数や残余引数(rest parameters)については後の章で扱います。

return で値を呼び出し元に返す

console.log は出力に書き出すだけですが、return は呼び出し元に値を返してくれるので、その値をそのまま使えます。

index.js
Output
Click Run to see the output here.

return を書かないと、関数は undefined を返します:

index.js
Output
Click Run to see the output here.

return が実行された時点で、関数はそこで即終了します。メインの処理に入る前に例外的なケースを弾きたいときは、早期リターン(early return)で抜けるのが定石です。

index.js
Output
Click Run to see the output here.

アーリーリターンを使えば、本体が if/else のピラミッドにならずに済みます。

巻き上げ(ホイスティング):定義する前に呼び出せる

これは他の言語から来た人が本当に驚くポイントです。関数宣言は 巻き上げ(ホイスティング) されます。つまり JavaScript はコードを実行する前に、関数宣言をスコープの先頭へ移動してくれるのです。そのため、宣言より前の行で関数を呼び出しても普通に動きます。

index.js
Output
Click Run to see the output here.

このコードは問題なく動きます。JavaScriptエンジンは実行前にスコープをスキャンして square を関数として登録し、それから文を上から順に実行していくからです。

これは関数宣言と、それ以外の関数の書き方(関数式やアロー関数)との間にある、実際の挙動の違いです。後者は変数と同じようにホイスティングされるので、名前 は認識されるものの、値はその行に到達するまで代入されません。この違いについては、このあと詳しく見ていきます。

とはいえ多くのスタイルガイドでは、関数は呼び出す前に定義することを推奨しています。巻き上げ(ホイスティング)はあくまで安全網であって、そこに頼る書き方をすべきではありません。

関数宣言と関数式の違い

関数宣言 (function declaration) はそれ自体が独立した文になります。一方で 関数式 (function expression) は値として扱われる位置、つまり代入の右辺などに書かれるのが一般的です。

index.js
Output
Click Run to see the output here.

どちらも呼び出し可能な関数を作れますが、違いは次のとおりです。

  • 関数宣言は丸ごと巻き上げ(ホイスティング)されます。一方の関数式は、代入される変数のホイスティングルールに従います(constlet はその行が実行されるまで一時的死角(TDZ)にいます)。
  • 宣言には必ず名前が必要です。関数式は無名でも書けますが、名前を付けておくとスタックトレースで追いやすくなります。
  • 関数宣言はどこにでも書けるわけではありません。strict モードでは if ブロック内の function foo() {} はエンジンによって挙動がバラバラなので、そういう場所では関数式を使いましょう。

ファイルのトップレベルに置くヘルパー関数なら、関数宣言のほうが読みやすいことが多いです。引数として渡す関数や、プロパティに代入する関数には、関数式(もしくはアロー関数)を使うのが一般的です。

命名とスタイル

関数名は、その関数が何をするかの「約束」です。少し手間をかけてでも分かりやすい名前を選んでおくと、誰かがそのコードを初めて読むそのときに、ちゃんと元が取れます。

index.js
Output
Click Run to see the output here.

押さえておきたい命名ルールをいくつか挙げておきます。

  • 関数名は動詞にします。たとえば fetchProfilecomputeTotalsendEmail といった具合です。
  • 表記は camelCase で。これが JavaScript の慣習です。
  • 真偽値を返す関数は ishascan で始めることが多いです。isValidhasAccesscanEdit などですね。

こうしておくと、呼び出し側のコードがそのまま英文のように読めるようになります。

実践的なサンプルコード

ここまで見てきた引数、早期 return、わかりやすい関数名を組み合わせて、ひとつの例にまとめてみましょう。

index.js
Output
Click Run to see the output here.

宣言ひとつ、ガード節ひとつ、そして明快な return。この形さえ押さえておけば、実際に書く関数のほとんどはカバーできます。

次はアロー関数

関数宣言が基本の道具であることは間違いありませんが、モダンな JavaScript ではもっと短い書き方——アロー関数——が頻繁に使われます。特にコールバックや 1 行で済む処理では主役と言ってもいいでしょう。見た目も違えば this の扱いも違う、そんなアロー関数を次のページで取り上げます。

よくある質問

JavaScriptで関数を宣言するにはどう書けばいい?

functionキーワードのあとに関数名、()に引数、{}に処理本体を書きます。例:function greet(name) { return 'Hi, ' + name; }。呼び出すときはgreet('Ada')のように名前に()を付けて実行します。

関数の巻き上げ(ホイスティング)とは?

関数宣言はコードが実行される前にスコープの先頭に巻き上げられるので、定義より上の行から呼び出してもちゃんと動きます。ただしこの挙動が効くのはfunction宣言だけ。letconstに代入した関数式やアロー関数は同じようには巻き上がらないので注意してください。

関数宣言と関数式の違いは?

関数宣言はfunction greet() {}のように単独の文として書け、巻き上げの対象になります。一方の関数式はconst greet = function() {}のように変数へ代入する形で、変数の巻き上げルールに従います。宣言は必ず名前を持ちますが、関数式は無名で書かれることが多いのも違いのひとつです。

Coddyでコードを学ぼう

始める