みこむらめもむらむらむら

なんかHTML5とかJS勉強とかやりながらめもを綴るブログ

【JavaScript】関数とは

あ、テキストは下記を使用して勉強中
JavaScript本格入門 ~モダンスタイルによる基礎からAjax・jQueryまで
いよいよやってまいりました関数!ひゃほー!

関数を定義する3つの方法

与えられた入力(パラメータ)に基づいて何らかの処理を行い
その結果を返す仕組みを関数という
JavaScriptではデフォルトでも多くの関数を提供しているが
アプリケーション開発者が自分で関数を定義することもできる

ユーザ定義関数を定義するには大きく3つの方法がある

  1. function命令で定義する
  2. Functionコンストラクタ経由で定義する
  3. 関数リテラル表現で定義する

ふむふむ‥それぞれを詳しく見ていく!

function命令で定義する

function 関数名([引数1[, 引数2[, ..]]]) {
  関数内で実行される任意の命令(群)
  [return 戻り値;]
}

関数名にについては下記2点に注意

  1. (単なる文字列や式でなく)識別子を指定する必要がある
    • 1文字目は英字/アンダースコア(_)/ドル記号($)のどれか
    • 2文字目以降は、1文字目で利用可能な文字か数字
    • 変数名に含まれる英数字の小文字/大文字は区別される
    • JSで意味を持つ予約語じゃないこと
  2. 「その関数が何の処理をしているのか」がすぐわかるような名前をつける
    • 「showMessage」のように「動詞+名詞」の形式で命名するのが一般的

引数は関数の挙動を決めるためのパラメータ
ここでは呼び出し元から指定された値を
受け取るための変数をカンマ区切りで指定する

引数を受け取るための変数は仮変数をも云い、
関数の内部でのみ参照できる

戻り値は、関数が処理の結果
最終的に呼び出し元に返すための値のこと
通常、関数の末尾にreturn命令を記述して指定する
関数の途中でreturn命令を記述した場合
それ以降の処理は実行されないので要注意
関数の途中で記述する場合は
if/switchなどの条件分岐を合わせて利用するべき

戻り値がない、呼び出し元に値を返さない関数では
return命令を省略しても問題ない
return命令が省略された場合
関数はデフォルトでundefined(未定義値)を返す

定義済みの関数は以下のようにして呼び出す

関数名([引数, ..]);

それでは構文の説明からの具体例!

function triangle(base, height) {
  return base * height / 2;
}

document.writeln('三角形の面積:' + triangle(5, 2));  //5

上記のtriangle関数は引数として
変数base(底辺)、height(高さ)を受け取り
戻り値として三角形の面積を返すための関数である

引数が存在しない場合にも
関数の後方の丸カッコは省略できないので注意

はあく!(・∀・)

Functionコンストラクタ経由で定義する

JavaScriptでは組み込みオブジェクトとして
Functionオブジェクトを用意している
関数はこのFunctionオブジェクトの
コンストラクタを利用して定義することもできる

var 変数名 = new Function([引数[, 引数2[, ..,]]], 関数の本体)

たとえばさっきのtriangle関数を
コンストラクタ経由で書き換えると下記のようになる

var triangle = new Function('base', 'height', 'return base * height / 2;');
document.writeln('三角形の面積:' + triangle(5, 2));  //5

Functionコンストラクタには関数が受け取る仮引数を順に並べ
最後に関数本体を指定するのが基本である
String、Number、Booleanなどのオブジェクトと同じく
new演算子を省略してあたかもグローバル関数であるかのように
記述することもできる

var triangle = Function('base', 'height', 'return base * height / 2;');

また、以下のように仮引数の部分を
ひとつの引数として記述することもできる

var triangle = Function('base, height', 'return base * height / 2;');

ここでは本文に分が一つしか含まれない関数を定義しているが
通常の関数定義と同様、セミコロン(;)で文を区切って
複数の文を含めることもできる

先ほどのfunction命令を使わずに
あえてFunctionコンストラクタを利用するメリットは
「引数や関数本体を文字列として定義できる」ことである

var param = 'height, width';
var formula = 'return height * width / 2;';
var diamond = new Function(param, formula);
document.writeln('ひし形の面積:' + diamond(5, 2));  //5

ここでは単純化のため
変数param、formulaをそれぞれ固定値で指定しているが
スクリプト上で文字列連結して
引数/関数本体を動的に生成することもできる
ただしこのような使い方は
eval関数のときに述べたのと同じ下記理由で濫用すべきではない

  • 第3者による任意のスクリプトが自由に実行できてしまう可能性がある(セキュリティリスク)
  • 通常のコードを実行するよりも処理速度が遅い(パフォーマンスの劣化)

JavaScriptの関数は基本的にfunction命令
または後述する関数リテラルで定義する

と覚えておく、はい!

関数リテラル表現で定義する

JavaScriptにおいて関数はデータ型の一種である
つまり、関数を変数に代入したり、ある関数の引数として渡したり
あるいは、戻り値として関数を返すことすら可能である
これによってJavaScriptは柔軟なコーディングが可能になる

さっきのtriangle関数を
関数リテラルで書き換えると下記のようになる

var triangle = function(base, height) {
  return base * height / 2;
}

document.writeln('三角形の面積:' + triangle(5, 2));  //5

関数リテラルの記法はfunction命令によく似ているが
以下のような違いがある

  • function命令
    • 関数triangleを直接定義している
  • 関数リテラル
    • 「function(base, height) {..}」と名前のない関数を定義上で変数triangleに格納している

関数リテラルは宣言した時点では名前を持たないことから
匿名関数、または無名関数と呼ばれることもある
匿名関数はJavaScriptの関数を利用する上で大変重要な概念である
詳細は後述かーああーなるほどです