JavaScriptの関数は任意の引数をとる

JavaScriptには驚かされます。次のように関数に引数が全く定義されていない場合でも、関数は引数が定義されたものとして実行することが可能です。

[sourcecode language="JavaScript"] var max_value = max(1,100,200,10,90,"hoge"); document.write("max_value = " + max_value);

function max(){ var m = Number.NEGATIVE_INFINITY;

// 任意の個数の引数のうち最大値を取得する
for(var i = 0; i < arguments.length;i++){

    document.write("arguments[" + i + "]=" + arguments[i] + "<br />");

    // 文字列を数値に変換する
    var num = parseFloat(arguments[i]);

    if(isNaN(num)){
        document.write("parseFloat result is NaN. >> arguments[" + i + "]=" + num + "は数値ではありません。" + "<br />");
        continue;
    }

    if(arguments[i] > m){
        m = arguments[i];
    }
}

return m;

}

--- 実行結果 arguments[0]=1 arguments[1]=100 arguments[2]=200 arguments[3]=10 arguments[4]=90 arguments[5]=hoge parseFloat result is NaN. >> arguments[5]=NaNは数値ではありません。 max_value = 200

[/sourcecode]

ここで登場する arguments がとても重要です。というのも、JavaScriptでは関数の引数が定義されていても、任意の引数を設定することが可能だからです。

[sourcecode language="JavaScript"] var max_value = max(1,100,200,10,90,"hoge"); document.write("max_value = " + max_value);

function max(a, b){ var m = Number.NEGATIVE_INFINITY;

document.write("a=" + a + "<br />");
document.write("b=" + b + "<br />");

// 任意の個数の引数のうち最大値を取得する
for(var i = 0; i < arguments.length;i++){

    document.write("arguments[" + i + "]=" + arguments[i] + "<br />");

    // 文字列を数値に変換する
    var num = parseFloat(arguments[i]);

    if(isNaN(num)){
        document.write("parseFloat result is NaN. >> arguments[" + i + "]=" + num + "は数値ではありません。" + "<br />");
        continue;
    }

    if(arguments[i] > m){
        m = arguments[i];
    }
}

return m;

}

--- 実行結果 a=1 b=100 arguments[0]=1 arguments[1]=100 arguments[2]=200 arguments[3]=10 arguments[4]=90 arguments[5]=hoge parseFloat result is NaN. >> arguments[5]=NaNは数値ではありません。 max_value = 200 [/sourcecode]

これは最初のメソッドにメソッドの引数として a と b を追加しただけです。事実、引数として定義された a と b はメソッドの先頭で参照が可能となっています。ただ、それ以外の引数が存在することも確かです。

このように、JavaScriptのメソッドでは引数の定義は単なる引数に名前をつけるだけの効果しかないようです。 そこで引数の実態はというと arguments オブジェクトとなるわけです。この arguments オブジェクトが引数を管理しているオブジェクトになります。従って、引数は arguments オブジェクトを中心に操作する方がいいのではないかしらと思えてきますね。

なお、サイ本によるとこの arguments は予約語として定義されていないそうです。