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で大きな配列をチェックするのは危険かも。あと、予想以上にFirefoxがIEより速かった。IEは6.0、Firefoxは1.5です。