JavaScriptのargumentsはArrayじゃない

Function.prototype.curry = function(t) {
    var self = this;
    return function() {
        return self.apply(this, [t].concat(arguments));
    }
}

のような関数をカリー化引数を部分適用させるメソッドを作ってみたが上手く動作しない。arguments は Array オブジェクトではないので、[t].concat(arguments)はフラットな配列として展開されないのだった。

function hoge() {
     window.alert(arguments);   // object Arguments
     window.alert(arguments instanceof Array); // false
}
hoge();

JavaScript には、arguments 以外にも、DOM の NodeList とか、form のチェックボックスとか Array オブジェクトではないけれど、配列っぽく見える曲者がいくつか存在している。そんな曲者たちはIT戦記 - arguments を直接的に配列化によると

var array = Array.prototype.slice.call(arguments, 0, arguments.length);

というコードで Array に変換できる。この場合、第二、第三引数は省略可。さらにFirefox 2.0では

var array = Array.slice(arguments);

と簡単に書けて素晴らしい。

んで、最初のカリー化部分適用メソッドは

Function.prototype.curry = function(t) {
    var self = this;
    return function() {
        return self.apply(this, [t].concat(Array.prototype.slice.call(arguments)));
    }
}

こんな感じかな。