JavaScript/Function
関数(かんすう、function)とは、コードのまとまりです。
概要[編集]
関数はプログラムの中に繰り返し現れるような同じコードや、意味がそろっているコードを一つの手続きとしてまとめるために用いられます。JavaScriptの関数はfunction文を使って定義します。
function add(a, b) { var sum = a + b; return sum; } var three = add(1, 2); // 1 + 2 alert(three); // 3
これは数値a, bを受け取り、aとbを足した結果sumを返すadd関数の例です。aやbのように関数が受け取るデータを引数(ひきすう、parameter)、sumのように関数が返す値を戻り値(もどりち、return value)あるいは返り値(かえりち)といいます。戻り値はreturn文を使って返します。
関数を呼び出すには、add(1, 2)のように関数の名前の後に()を付けて、()の中に引数として関数に渡す値を入れます。関数が呼び出されると、1はa、2はbに代入されて、関数の本体が実行され、足し算の結果が返されます。
aやbのように関数が受け取ると仮定された引数を仮引数(かりひきすう、かびきすう、parameter)、1や2のように関数に実際に渡した引数を実引数(じつひきすう)といいます。余裕のある人は憶えてください。
関数リテラル[編集]
JavaScriptにおける関数はオブジェクト(object)の一種であり、ArrayオブジェクトやStringオブジェクトなど、他のオブジェクトと同じように操作することができます。
var add = function(a, b){ return a + b; }; alert( add(1, 1) ); // 1 + 1 == 2
このようなオブジェクトを第一級オブジェクト(だいいっきゅうオブジェクト、first-class object)といいます。JavaScriptは関数を第一級オブジェクトとして扱えるので、第一級関数(だいいっきゅうかんすう、first-class function)をサポートしています。
関数スコープ[編集]
関数の中でvarキーワードを用いて宣言された変数は、関数の中からしか見えません。
var f = function(){ var i = 0; return i; }; alert( f() ); // 0 alert(i); // 参照エラー
言い換えれば、関数の中でvarキーワードを用いて宣言された変数と、関数の外で宣言された変数は別物です。
var f = function(){ var i = 0; return i; }; var i = 1; alert(i); // 1 alert( f() ); // 0
Function[編集]
JavaScriptの関数の実体はすべてFunctionオブジェクトです。
var add = new Function('a', 'b', 'return a + b'); alert( add(1, 1) ); // 1 + 1 == 2
Functionオブジェクトのコンストラクタは最初に仮引数を表す文字列をいくつか受け取り、最後の引数として関数の本体を表す文字列を受け取ります。
プロパティ[編集]
- Functionオブジェクトのプロトタイプです。
標準グローバル関数[編集]
- decodeURI
- decodeURIComponent
- encodeURI
- encodeURIComponent
- eval
- isFinite
- isNaN
- parseFloat
- parseInt
- void
再帰[編集]
再帰とは、関数が自分自身を呼び出すことをいいます。
// 階乗 n! function factorial(n) { return n ? n * factorial(n - 1) : 1; } alert( factorial(5) ); // 120 // n 番目のフィボナッチ数 function fibonacci(n) { return n < 2 ? n : fibonacci(n - 2) + fibonacci(n - 1); } alert( fibonacci(10) ); // 55 // a, b の最大公約数 function gcd(a, b) { return b ? gcd(b, a % b) : Math.abs(a); } alert( gcd(42, 56) ); // 14
脱出条件を間違えて無限ループにならないように注意してください。
無名関数[編集]
無名関数(むめいかんすう)または匿名関数(とくめいかんすう、anonymous function)とは、名前のない関数を指します。
(function(a, b){ alert(a + b); // "3" と警告 })(1, 2);
無名再帰[編集]
無名関数の再帰を無名再帰(むめいさいき)または匿名再帰(とくめいさいき、anonymous recursion)といいます。JavaScriptで無名再帰を行うには、関数の中で自分自身を指すarguments.calleeプロパティを使用します。
// 階乗 n! (function(n){ return n ? n * arguments.callee(n - 1) : 1; })(5); // n 番目のフィボナッチ数 (function(n){ return n < 2 ? n : arguments.callee(n - 2) + arguments.callee(n - 1); })(10); // a, b の最大公約数 (function(a, b){ return b ? arguments.callee(b, a % b) : Math.abs(a); })(42, 56);
arguments.calleeプロパティを使用せずに無名再帰を行うには、不動点コンビネータ(ふどうてんコンビネータ、fixed point combinator、不動点演算子、ふどうてんえんざんし、fixed-point operator)を用います。
// 不動点コンビネータ var Z = function(f){ return function(x){ return function(y){ return f( x(x) )(y); }; }(function(x){ return function(y){ return f( x(x) )(y); }; }); }; // 階乗 n! Z(function(f){ return function(n){ return n ? n * f(n - 1) : 1; }; })(5); // n 番目のフィボナッチ数 Z(function(f){ return function(n){ return n < 2 ? n : f(n - 2) + f(n - 1); }; })(10); // a, b の最大公約数 Z(function(f){ return function(a){ return function(b){ return b ? f(b)(a % b) : Math.abs(a); }; }; })(42)(56);
ラムダ計算も参照してください。
クロージャ[編集]
クロージャ(closure、閉包、へいほう)とは、引数以外のすべての変数を静的スコープ(せいてきスコープ、static scoping、構文スコープ、lexical scoping、レキシカルスコープ)で解決する関数のことです。教科書などによく出てくる典型的なクロージャは、次のようなカウンタ変数を用いた例です。
// 関数を返す関数 var f = function(){ var i = 0; return function(){ return i++; }; }; var g = f(); alert( g() ); // 0 alert( g() ); // 1 alert( g() ); // 2 var i = 0; // カウンタ変数を書き換えても alert( g() ); // 3 -- 値は変わらない
関数fは変数iをインクリメントして返す関数を返す関数です。ややこしいですが、fによって生成された関数gを呼び出すと、iの値が0, 1, 2, ...と1ずつ増やして返されます。ここでiの値を書き換えても、gの中のiの値は変わりません。gはクロージャになっているからです(gを呼び出したときではなく、gを定義したときのiを参照している)。
関数fの中の変数iに注目してください。iはfの中でvarキーワードを用いて宣言されているので、関数スコープになり、fを出た時点で消滅するはずです。しかし、関数gを呼び出すとなおiをインクリメントした値が返ってきます。繰り返しになりますが、クロージャとは引数以外のすべての変数を、呼び出した時点ではなく定義した時点で解決する関数のことでした。fが返す関数を定義した時点ではiが生きていたので、iが見えなくなってもiの値を参照しつづけられるというわけです。