arguments に対して shift するための考察(をしていたらカッとなって配列変換のベンチマーク)
JavaScript において可変引数を扱う場合
arguments オブジェクトを使います。
function func() { for (var i = 0; i < arguments.length; i ++) { alert(arguments[i]); } }; func(1,2,3) // 1,2,3 を順に表示
そして
可変引数を使うパターンとしては、
- すべて可変引数
- 固定引数と可変引数
の二つに分けることができます。
すべて可変引数
引数が与えられた分だけ同じような処理を行うパターン
function add() { for (var i = 0, r = 0; i < arguments.length; i ++) r += arguments[0]; return r; } var r = add(1, 2, 3, 4, 5);
固定引数と可変引数
最初のいくつかの引数には特別な意味があり、余った引数は引数が与えられた分だけ同じ目的で使われるパターン
function multiCall() { var func = arguments[0]; // 最初の引数 // 残りの引数 for (var i = 1; i < arguments.length; i ++) func(arguments[i]); } multiCall(alert, 'hello', 'amachang'); // hello, amachang と順に表示
最初のパターンは簡単でいいのですが、二個目のパターンは固定部が複雑になってくると引数の解析がめんどくさくなってしまいます。
という訳で
function func() { var shift = Array.prototype.shift; var a = shift.apply(arguments); var b = shift.apply(arguments); // この時点で arguments は第一引数と第二引数を抜かしたものになってる。 };
はい。これは便利ですね。
しかし!現状の Opera 9 にはバグがあって shift.apply(arguments) に失敗して、 arguments を壊してしまいます。
orz
という訳で
現状クロスブラウザな解決策としては配列に変換して shift を使うか、 Opera の shift を上書きするかしかありません><
残念><
おしまい><
。。。ってこんな締めはあんまりなので
おまけ(arguments を配列に変換する方法 3 種類のベンチマーク)
arguments を配列に変換するクロスブラウザな三つの方法を考えてベンチマークを取ってみました。
1. for 文を使う
function test() { // ここから var r = []; for (var j = 0, l = arguments.length; j < l; j ++) { r.push(arguments[i]); } // ここまでをベンチ }
2. push を使う
function test() { // ここから var r = []; r.push.apply(r, arguments); // ここまでをベンチ }
3. concat を使う
function test() { // ここから var r = []; r = r.concat.apply(r, arguments); // ここまでをベンチ }
ベンチマーク
表中の単位は ms。 Windows と Mac のスペックは違うので縦軸の比較はできません
引数 10 個の場合
環境 | for | push | concat |
---|---|---|---|
Mac+Firefox2 | 0.0214 | 0.01399 | 0.01667 |
Mac+Opera9 | 0.01443 | 0.00576 | 0.00647 |
Mac+Safari3 | 0.0129 | 0.00414 | 0.00436 |
Win+IE6 | 0.03172 | 0.01187 | 0.015 |
Win+IE7 | 0.03453 | 0.01485 | 0.01906 |
引数 100 個の場合
環境 | for | push | concat |
---|---|---|---|
Mac+Firefox2 | 0.1872 | 0.0881 | 0.01667 |
Mac+Opera9 | 0.1356 | 0.0421 | 0.0433 |
Mac+Safari3 | 0.1144 | 0.0301 | 0.00297 |
Win+IE6 | 0.2891 | 0.0672 | 0.0719 |
Win+IE7 | 0.2922 | 0.075 | 0.0812 |
引数 1000 個の場合
環境 | for | push | concat | |
---|---|---|---|---|
Mac+Firefox2 | 1.589 | 0.723 | 0,726 | |
Mac+Opera9 | 1.406 | 0.4 | 0.425 | |
Mac+Safari3 | 0.761 | 0.287 | 0.285 | |
Win+IE6 | 2.796 | 0.61 | 0.64 | |
Win+IE7 | 2.828 | 0.672 | 0.703 |