Array.prototype.includeが遅い!

prototype-1.4.0.jsのArrayのあたりを読んでたら、どうもincludeに時間がかかりそうな予感がしたので、調べてみたら本当に遅かった。

  include: function(object) {
    var found = false;
    this.each(function(value) {
      if (value == object) {
        found = true;
        throw $break;
      }
    });
    return found;
  },

実際はEnumerable(クラスではなくRubyで言うモジュールみたいなもの)のところに書いてあるけど、Array.prototypeにも適用されてる。
で、早くなることを祈ってこんな感じで書いてみた。メソッド名はcontainsとして元々のincludeと区別してます。

Object.extend( Array.prototype, {
  contains: function( obj ) {
    return this.indexOf( obj ) > -1;
  }
}

indexOfメソッドは、prototype.jsでArray.prototypeに追加されてるメソッド。

こんな感じで計ってみた。

function test_Array_include_and_contains() {
	var count = 100000;
	var array = new ObjectRange(1, count).toArray();
	//
	var contains_start = new Date().getTime();
	array.contains( count -1);
	var contains_end = new Date().getTime();
	//
	var include_start = new Date().getTime();
	array.include( count -1);
	var include_end = new Date().getTime();
	//
	alert("contains: " + (contains_end - contains_start) + "msec " + "include: " + (include_end - include_start) + "msec");
}

countの数だけ配列を用意して、その最後から2番目の数値を検索する。
僕のマシンでは、以下の結果が出ました。(count以外の単位はミリ秒)

count include(IE) contains(IE) include(FX) contains(FX)
1000 16 0 0 0
10000 125 16 31 0
100000 3078 79 265 47

うーん、includeで大きな配列をチェックするのは危険かも。あと、予想以上にFirefoxIEより速かった。IEは6.0、Firefoxは1.5です。