JavaScript重箱の隅  新JavaScript入門  JavaScript,Neo-Generation  掲示板  表紙
1. and と or  3. Number 
JavaScript 重箱の隅
Written 2/23/00
for
よく次のように配列のすべての要素について処理することがあります。
  var ary = new Array();
   …
  for(var i = 0; i < ary.length; i++)
    …
 
「オブジェクトのプロパティを見に行くとめちゃ時間がかかる」 というのはよく言われるのですが、 ary.length はループしている間変化しなくても毎度見に行くのでしょうか。

次の2つのコードでループにどれくらい時間がかかるか見てみましょう。 上は ary.length を使い、下はあらかじめ n としています。

  var n = 100000;
  var ary = new Array();
  for(var i = 0; i < n; i++)
    ary[i] = i % 2 ? i : -i;        //0,1,-2,3,-4,5,…

  var time = new Date();
  var sum = 0;
  for(var i = 0; i < ary.length; i++)
    sum += ary[i];

  alert((new Date() - time) + "msec");
  alert(sum);
 
  var n = 100000;
  var ary = new Array();
  for(var i = 0; i < n; i++)
    ary[i] = i % 2 ? i : -i;

  var time = new Date();
  var sum = 0;
  for(var i = 0; i < n; i++)
    sum += ary[i];

  alert((new Date() - time) + "msec");
  alert(sum);
 
うちの環境では、上より下は、IE では 12%、 ネスケでは 40% も速いという結果が出ました。
やっぱり何にも最適化されずに毎回プロパティを見に行くんですね。

ary.length を使わない方法に、for(i in ary) を使う方法があります。

  //前略
  for(var i in ary)
    sum += ary[i];
  //後略
 
これはむちゃくちゃ遅いですね。 特に IE ではどうしようもなく遅いです。 インデックスを使っているので速くなるはずがないのですが。

ネスケだと shiftpop を使うとインデックスを使わずに済みます。

  //前略
  var a;
  while((a = ary.pop()) != undefined)
    sum += a;
  //後略
 
さらに遅いですね。「はう〜」という感嘆詞が口をついてきます。 ちなみに shift だとどうにも遅くて、 我慢できずに kill してしまいました。 先頭のアドレスが移動するんじゃなくて本当にデータが shift してるんですね、きっと(爆)。

かなり脱線してしまいましたが、
結論的には、ふつうに、まじめに書くのがいちばんってことですね。 というか、JavaScript で大きなデータを扱わない方がいいってことか。
というなげやりな結論よりも、 やっぱり JavaScript にも配列の要素を取り出す構文がほしいですね。 それ以前に、ちゃんとメモリを確保してまともな配列にしてほしいです。

first, prev, next, exit