スクリプトの色々な場所で同じアクションを実行する必要がある場合がよくあります。
例えば、訪問者がログイン/ログアウトしたり、また複数の箇所で見栄の良いメッセージを表示する必要があったりします。
関数はプログラムのメインの “構成要素” です。これによりコードを繰り返すことなく何度も呼び出すことができます。
私たちは既に組み込み関数の例を見ています。 alert(message), prompt(message, default) や confirm(question)です。これと同じように私たち自身も関数を作ることができます。
関数定義
関数を作るために、関数定義 を使います。
次のようになります:
function showMessage() {
alert( 'Hello everyone!' );
}
function キーワードが最初にきて、次に 関数名 がきます、そして括弧の中に パラメータ のリスト(カンマ区切り、上の例では空)がきて、最後に中括弧の間に関数のコード、 “関数本体” です。
function name(parameters) {
...body...
}
作成した関数はその関数名で呼び出すことができます: showMessage()
例:
function showMessage() {
alert( 'Hello everyone!' );
}
showMessage();
showMessage();
showMessage() の呼び出しは、関数のコードを実行します。この例では、2度メッセージが表示されます。
この例は関数のメインの目的の1つを明確に示しています: コードの複製を回避する、と言うことです。
もしメッセージ内容、または表示方法を変更する必要がある場合、1箇所のコード(関数)を修正するだけで十分です。
ローカル変数
関数内で定義された変数は、関数内でのみ参照可能です。
例:
function showMessage() {
let message = "Hello, I'm JavaScript!"; // ローカル変数
alert( message );
}
showMessage(); // Hello, I'm JavaScript!
alert( message ); // <-- エラー! 変数は関数のローカルです
外部変数
関数は外部変数にアクセスすることもできます。次の例を見てください:
let userName = 'John';
function showMessage() {
let message = 'Hello, ' + userName;
alert(message);
}
showMessage(); // Hello, John
関数は外部変数に対してフルアクセス権を持ち、変更することもできます。
例:
let userName = 'John';
function showMessage() {
userName = "Bob"; // (1) 外部変数の変更
let message = 'Hello, ' + userName;
alert(message);
}
alert( userName ); // 関数呼び出しの前は John
showMessage();
alert( userName ); // Bob, 関数によって値が変更されました
外部の変数は、同じ名前のローカル変数が存在しない場合にのみ使われます。そのため、let を忘れた場合、意図せず外部の変数を変更してしまう可能性があります。
同じ名前の変数が関数内に宣言されている場合は、外部変数を 隠します。例えば、以下のコードでは関数はローカルの userName を使います。外部の userName は無視されます。
let userName = 'John';
function showMessage() {
let userName = "Bob"; // ローカル変数の宣言
let message = 'Hello, ' + userName; // Bob
alert(message);
}
// 関数は作られ独自の userName を使います
showMessage();
alert( userName ); // John, 変更されていません。関数は外部変数へアクセスしませんでした
上のコードにおいて、外部の userName のような、関数の外で宣言されている変数は グローバル と呼ばれます。
グローバル変数はどの関数からも見えます(ローカル変数により隠れていなければ)。
通常、関数は自身のタスクに必要なすべての変数を宣言します。また、グローバル変数にはプロジェクトレベルのデータのみを保持するため、どこからでも見える事が重要です。現代のコードはほとんどもしくは全くグローバル変数を持ちません。ほぼすべての変数は関数に属します。
パラメータ
パラメータを使うことで、任意のデータを関数に渡すことができます。
下の例では、関数は2つのパラメータを持っています: from と text です。
function showMessage(from, text) { // 引数: from, text
alert(from + ': ' + text);
}
showMessage('Ann', 'Hello!'); // Ann: Hello! (*)
showMessage('Ann', "What's up?"); // Ann: What's up? (**)
行 (*) と (**) で関数が呼ばれたとき、与えられた値はローカル変数 from と text にコピーされます。そして関数はそれらを使います。
ここにもう1つ例があります: 私たちは変数 from を持っており、それを関数に渡します。注意してください:関数は常に値のコピーを取得するため、関数の中の処理は from を変更していますが、その変更は外には見えません:
function showMessage(from, text) {
from = '*' + from + '*'; // "from" をより良く見せる
alert( from + ': ' + text );
}
let from = "Ann";
showMessage(from, "Hello"); // *Ann*: Hello
// "from" の値は同じで、関数はローカルコピーを変更しています。
alert( from ); // Ann
関数のパラメータとして渡された値は “引数(ひきすう)” とも呼ばれます。 これらの用語を整理すると:
- パラメータとは、関数の宣言時に括弧内に記述される変数のこと(宣言時の用語)
- 引数とは、関数が呼び出されたときに渡される値のこと(呼び出し時の用語)
パラメータを列挙して関数を宣言し、引数を渡して関数を呼び出すことになります。
上の例ではこのように言えるでしょう。「関数showMessageは2つのパラメータを持つと宣言されており、from と “Hello” という2つの引数を与えて呼び出されている」
デフォルト値
関数の呼び出し時に引数が与えられていない場合、対応する値は undefined になります。
例えば、前述の関数 showMessage(from, text) は1つの引数で呼ぶことも出来ます:
showMessage("Ann");
それはエラーではありません。このような呼び出しは "*Ann*: undefined" を出力します。text が渡されていないため、text は undefined となります。
パラメータのいわゆる “デフォルト” (呼び出し時に省略された場合に使用される)値を、関数宣言の中で = を使用して指定することが可能です:
function showMessage(from, text = "no text given") {
alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given
これで text パラメータが渡されていない場合、 値は "no text given" になります。
ここで、 "no text given" は文字列ですが、より複雑な式にすることもできます。そしてそれはパラメータが無い場合にのみ評価され、代入されます。なので、このようなことも可能です:
function showMessage(from, text = anotherFunction()) {
// anotherFunction() はテキストが与えられなかった場合にのみ実行されます
// その結果がtextの値になります
}
JavaScriptでは、デフォルト値はそれぞれのパラメータが与えられずに関数が呼び出されるたびに評価されます。
上の例だと anotherFunction() は、 text のパラメータが与えられずに showMessage() が呼び出されるたびに実行されます。
代替のデフォルトパラメータ
パラメータのデフォルト値を関数宣言ではなく、後の段階で実行中に設定することが理にかなっている場合があります。
省略されたパラメータをチェックするために、undefined と比較できます:
function showMessage(text) {
if (text === undefined) {
text = 'empty message';
}
alert(text);
}
showMessage(); // empty message
…もしくは || 演算子:
// パラメータが省略 or "" の場合, 'empty' を設定
function showMessage(text) {
text = text || 'empty';
...
}
モダンな JavaScript エンジンは NULL合体演算子 ?? をサポートしており、0 などの偽値を通常とみなす場合に適しています:
// count パラメータがない場合は "unknown"
function showCount(count) {
alert(count ?? "unknown");
}
showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown
値の返却
関数は、実行結果として呼び出しコードに値を戻すことが出来ます。
最もシンプルな例は2つの値の合計を行う関数です:
function sum(a, b) {
return a + b;
}
let result = sum(1, 2);
alert( result ); // 3
ディレクティブ return は関数の任意の場所に置くことが出来ます。もしも実行がそこに到達したとき、関数は停止し、値を呼び出し元のコードに返します(上の result へ代入します)。
1つの関数に多くの return が出現することもあります。例えば: