JavaScriptの関数の実体は、Functionオブジェクトです。
プロパティ | 内容 |
---|---|
caller | 呼び出し元の関数 |
constructor | オブジェクトを生成した関数 |
arguments | (非推奨) 引数の配列 |
lenth | 引数の数 |
name | 関数の名前 |
メソッド | 説明 |
---|---|
apply | 関数を呼び出す (引数は配列) |
call | 関数を呼び出す (引数は変数の羅列) |
toSource | 関数のソースコードを返す |
toString |
関数は、functionキーワードにより定義できます。
function FunctionName( x, y ) { return x * y; }
関数リテラルでは関数名を省略できます。このように定義された関数は、
などと呼ばれ、変数に格納したり他の関数に渡すためにだけ定義される関数の記述に適しています。
var FunctionName = function( x, y ) { return x * y; }
なおJavaScript 1.5以降では関数リテラルでも関数名を付けることができ、再帰関数を作ることができます。
関数を実行時に動的に生成できます。以下のコードは、前述のコードと同義のものです。
var FunctionName = new Function( 'x', 'y', 'return x * y;' );
関数の作成はfunctionではなくFunctionで行います。そして最後の引数が関数の本体となります。
JavaScriptにはC++のような関数の多重定義はなく、同名の関数を定義すると、先の関数が上書きされて呼び出せなくなります。
function Func( a ) { alert( a ); }
function Func( a, b ) { alert( a + b ); }
Func( 'X' ); // Xundefined
この例では後から定義された関数Func()が呼び出され、引数の数が不足しているため第2引数がundefinedとなっています。
多重定義はサポートされていませんが、Argumentsなどで関数側で細工をすれば、多重定義されているように振る舞わせることは可能です。
function Func1() { switch( arguments.length ) { case 1: // 引数が1つの場合の処理 break; case 2: // 引数が2つの… break; } }
function Func2( a ) { switch( typeof a ) { case 'number': // 引数が数値の場合の処理 break; case 'string': // 引数が文字列の… break; } }
オブジェクトのプロパティへアクセスするための関数 (メソッド) の代替として、ゲッター (accessor methods) とセッター (mutator methods) を定義できます。これは、C#のプロパティに相当する機能です。
Internet Explorerの場合、ゲッターとセッターにはIE9以降で対応します。
{get prop() { ... } }getter - JavaScript | MDN
{set prop(val) { . . . }}setter - JavaScript | MDN
たとえばゲッターは次のように定義でき、プロパティと同様にアクセスできるのにもかかわらず、より柔軟な結果を返せます。
var a = 1; var obj = { x: a, // プロパティ get y () { return a; } // ゲッター } alert( obj.x ); // 1 alert( obj.y ); // 1 a = 2; alert( obj.x ); // 1 … オブジェクト定義時の値を返す alert( obj.y ); // 2 … 現在の値を返す
アロー関数式、別名ファットアロー関数 (fat arrow function) を用いることで、関数を簡潔に記述できます。またthisのスコープを、その関数内に制限します。Arrow functions - JavaScript | MDN
([param] [, param]) => { statements }
param => expression
このアロー関数式には2013年6月現在、Firefoxしか対応していません。Browser compatibility - Arrow functions - JavaScript | MDN
このアロー関数式を用いると、たとえば次のような文字列中の特定の文字のみを大文字に置換するコードは、
var newText = text.replace( /[a-c]/g, function( str ) { return str.toUpperCase(); } );
functionキーワードを省いて次のように書き換えられます。
var newText = text.replace( /[a-c]/g, ( str ) => { return str.toUpperCase(); } );
さらにこの場合かっことreturnも省けるため、結果として次のようになります。
var newText = text.replace( /[a-c]/g, str => str.toUpperCase() );
関数の実行スコープは、実行時のスコープではなく定義時のスコープです。
関数を入れ子で定義したスコープチェーンには、入れ子関数の外側の関数が含まれるようになります。これにより入れ子にされた関数からは、外側の関数の引数やローカル変数にアクセスできます。
関数が呼び出されると、関数のスコープには関数定義時のスコープチェーンが追加され、次にCallオブジェクトがその先頭に追加されます。
var x; // グローバルオブジェクト function Func() { var x; // Func()のCallオブジェクト }
グローバルな空間での変数名やプロパティ名の衝突を避けるには、
( function( str ) // 匿名関数として定義 { var a = str; // この変数はこのスコープ内でのみ有効 } )( 'abc' ); // ここで関数が実行される
のように匿名関数を定義して実行します。この方法は他にも、
!function() { /* */ }(); ~function() { /* */ }(); -function() { /* */ }(); +function() { /* */ }();
のように記述できます。どれを選ぶかは好みですが、最初の「!」から始める方法が一般的のようです。
JavaScriptでは関数呼び出し時の引数の数は、問題とされません。
function FunctionName( x, y ) // 引数は2つ { alert( x ); // 結果は 10 alert( y ); // 結果は undefined } // 引数を1つだけ指定して、関数を呼び出す FunctionName( 10 );
なお呼び出された関数側では、arguments.lengthで渡された引数の数を知ることができます。
C言語のように引数の渡し方を明示的に指示する方法はなく、つねに値渡しです。オブジェクトも値渡しであり、それ自身の変更は呼び出し元へ影響しませんが、そのプロパティへの変更は呼び出し元へ作用します。
function Func( a, b, c ) { a = 2; b = {p: 2}; c.p = 2; } var x = 1; var y = {p: 1}; var z = {p: 1}; Func( x, y, z ); alert( x ); // 1 alert( y.p ); // 1 alert( z.p ); // 2 (呼び出し元へ作用する)
function fnName(param1 = defaultValue1, ..., paramN = defaultValueN) { /* ... */ }
ECMAScript 2015 (ES2015) 以降で使用できます。デフォルト引数 - JavaScript | MDN
非対応の環境では、次のようにundefinedのときに既定値を指定するようにします。
param1 = typeof param1 !== "undefined" ? param1 : defaultValue1;
関数内では、arguments変数によりArgumentsオブジェクトを参照できます。Argumentsオブジェクトは番号付けされたプロパティを持ち、これにより関数に渡された引数に配列のようにアクセスできます。
function Func( a, b, c ) { alert( a ); // 1 alert( b ); // 2 alert( c ); // undefined alert( arguments ); // [1, 2] } Func( 1, 2 );
変数名 | 説明 |
---|---|
arguments | 関数に渡された引数を格納しているオブジェクト |
arguments.length | 関数に渡された引数の数 |
arguments.callee | (非推奨) 実行中の関数への参照 |
arguments.caller | (廃止) 実行中の関数の呼び出し元の関数への参照 |
arguments.calleeは現在実行中の関数を参照しているため、これを使用することで名前がない関数も参照できます。また再帰呼び出しにも利用できます。
var func = function( x )
{
if( x < 2 )
{
return 1;
}
else
{
// 関数func()を呼び出す
return x * arguments.callee( x - 1 );
}
}
alert( func( 5 ) );
ECMAScript 5のStrictモードでは、calleeの使用が禁止されています。よってcalleeは使用せず、関数の名前で呼び出すようにします。arguments.callee - JavaScript | MDN