JavaScript おれおれ Advent Calendar 2011 – 15日目

JavaScriptの関数は関数オブジェクト(Functionのインスタンス)なので、メソッドを使う事ができます。中でも最も使用頻度が高いのが .apply()だと思います。

.apply()を使うとその関数を実行する事ができます。……というと「はてな?」ですが、着目すべきは実行する際のコンテキストと引数を自由に設定できるという点です。

例えば配列風のオブジェクトを考えます。このオブジェクトは配列じゃないので、Arrayインスタンスなら使えるはずのメソッドが使えません。

var arr = ["a", "b", "c"];
console.log(arr.length);  // => 3
console.log(arr[1]);  // => "b"
console.log(arr.join("/"));  // => "a/b/c"

var obj = {
  "0": "a",
  "1": "b",
  "2": "c",
  length: 3
};
console.log(obj.length);  // => 3
console.log(obj[1]);  // => "b"
console.log(obj.join("/"));  // TypeError: 'join'というメソッドはない

配列じゃない、でも配列のメソッドを使いたい……という時に便利なのが .apply()です。

var obj = {
  "0": "a",
  "1": "b",
  "2": "c",
  length: 3
};

var arr = [];
var join = arr.join;  // 関数オブジェクトを取得
console.log(join.apply(obj, ["/"]));  // => "a/b/c"

第1引数でメソッドを実行するオブジェクト、第2引数でメソッドに与える引数を配列で与えます。

ちなみに上記のコードの場合、関数オブジェクトを取得したり、Arrayインスタンスを作成したりするのは省略して、直接prototypeを見るのが普通だと思います。

console.log(Array.prototype.join.apply(obj, ["/"]));  // => "a/b/c"

実行するオブジェクトというのは、関数(メソッド)を実行するときthisになるオブジェクトの事です。

var obj1 = { id: 1 };
var obj2 = { id: 2 };

obj1.showId = function() { console.log(this.id); };

obj1.showId();  // => 1
obj1.showId.apply(obj2);  // => 2

関連