8.6 関数のプロパティとメソッド
- 関数は特殊なJavaScriptオブジェクト
→関数もプロパティやメソッドを持つ。
- typeofで調べると関数は「function」。
8.6.1 lengthプロパティ
- argument配列のlengthプロパティはその関数に実際に渡された引数の個数を示す。
- これに対し、関数自身のlengthプロパティは関数の引数リストで宣言された引数の個数を示す。
- 関数のlengthプロパティは、関数の中でも外でも使用できる。
- 関数に渡された引数の個数が想定どおりの数かどうかチェックする時に使える。
function check(args){
var actual = args.length;
var expected = args.callee.length;
if( actual != expected ){
throw new Error("Wrong number of arguments");
}
}
function f(x, y, z){
check(arguments);
return x + y + z;
}
8.6.2 prototypeプロパティ
- どの関数にも、あらかじめ定義された プロトタイプオブジェクト を参照する prototypeプロパティ がある。
- new演算子を伴うコンストラクタとして関数を使用する場合に、プロトタイプオブジェクトが使われる。
→prototypeプロパティについては9章で!
8.6.3 自分専用の関数プロパティの定義
- 呼び出された時に一意の識別値を返す関数(毎回異なる値を返す。)
→過去の履歴を保持しておき、呼び出されたときにその履歴情報にアクセスする必要がある。
→これをグローバル変数に格納することもできるが、関数の内部でしか使わない場合、関数のプロパティに格納するのが最適。
→これをグローバル変数に格納することもできるが、関数の内部でしか使わない場合、関数のプロパティに格納するのが最適。
例)
uniqueInteger.counter = 0;
function uniqueInteger(){
return uniqueInteger.counter++;
}
8.6.4 apply()メソッドとcall()メソッド
- すべての関数に対してcall()メソッドとapply()メソッドが存在する。
- これらのメソッドの最初の引数は、これから呼び出す関数の対象となるオブジェクトで、関数の本体のthisキーワードの値になる。
- 2番目以降の引数は、これから呼び出す関数に引数として渡される。
→あるオブジェクトのメソッドであるかのように関数を呼び出すことができる。
例)2つの引数を使用する関数f()を、オブジェクトobjのメソッドのように呼び出す
f.call(obj, 1, 2);
これは、次の記述とほぼ同じ意味になる。
o.m = f;
o.m(1, 2);
delete o.m;
apply()メソッドも、call()と同じような働きをするが、関数に渡す引数を配列形式で指定する。
上の例をapply()を用いて行う場合、下記のようになる。
上の例をapply()を用いて行う場合、下記のようになる。
f.apply(obj, [1, 2]);
例)配列に格納されているようその中から最大の数値を見つけたい場合
var biggest = Math.max.apply(null, array_of_numbersf);
8.7 ユーティリティ関数
オブジェクトや配列、関数を操作するのに便利な関数
例)オブジェクトのユーティリティ関数
//調査可能なプロパティ名を配列に格納し、その配列を返す
function getPropertyNames(obj){
var r = [];
for( name in obj ) r.push(name);
return r;
}
//fromからto(なければ、新規オブジェクト)に、調査可能なプロパティをコピーする。
function copyProperties(from, to){
if(!to) to = {};
for( p in from ) to[p] = from[p];
return to;
}
//上記と同様、プロパティをコピーするが、既にtoで定義されているプロパティは上書かない。
function copyUndefinedProperties(from, to){
for( p in from ){
if(!p in to) to[p] = from[p];
}
}
例)配列用
//配列aryの各要素に対し、その要素を引数にして指定した関数を呼び出し、
//関数から返された値がtrueとなった要素のみを抜き出した配列を返す。
function filterArray(ary, predicate){
var results = [];
var length = ary.length;
for( var i=0; i<length; i++ ){
var element = ary[i];
if(predicate(element)) results.push(element);
}
return results;
}
//配列aryの各要素を関数fncに引数として渡し、fncから
//返される値を要素として格納する配列を返す。
function mapArray(ary, fnc){
var r = [];
var length = ary.length;
for(var i=0; i<length; i++) r[i] = fnc(ary[i]);
return r;
}
例)関数用
//関数fncをオブジェクトobjのメソッドとして呼び出す関数を返す。
function bindMethod(obj, fnc){
return function(){ return fnc.apply(obj, arguments}
}
//呼び出し時に指定した引数の他に、あらかじめ指定した引数も含めて
//fncを呼び出す関数を返す。
function bindArguments(fnc /*, あらかじめ指定する引数... */){
var boundArgs = arguments;
return function(){
//引数の配列を作成する。
var args = [];
for(var i=1; i<boundArgs.length; i++) args.push(boundArgs[i]);
for(var i=0; i<arguments.length; i++) args.push(arguments[i]);
//この引数を使って関数を呼び出す。
return fnc.apply(this, args);
}
}