IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

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 と順に表示

最初のパターンは簡単でいいのですが、二個目のパターンは固定部が複雑になってくると引数の解析がめんどくさくなってしまいます。

という訳で

配列shift 関数を使ってみましょう

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 を使うか、 Operashift を上書きするかしかありません><
残念><
おしまい><


。。。ってこんな締めはあんまりなので

おまけ(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。 WindowsMac のスペックは違うので縦軸の比較はできません
引数 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
まとめ

arguments を配列に変換する場合は push を使った方法が一番いい。