IT戦記

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

一行で IE の JavaScript を高速化する方法

以下の一行をすべての JavaScript の前に読み込む

/*@cc_on _d=document;eval('var document=_d')@*/

この一行を読み込むことによって IE での document へのアクセスが 5 倍速くなります。

たとえば

以下のように、読み込む前と読み込んだ後を比較してみます。

// Before
var date = new Date;
for (var i = 0; i < 100000; i++) document; 

alert(new Date - date); // 643

/*@cc_on _d=document;eval('var document=_d')@*/

// After
date = new Date;
for (var i = 0; i < 100000; i++) document; 

alert(new Date - date); // 145

速くなってますね!

解説

まず、 IE では document にそのままアクセスすると window オブジェクトの内部メソッドが実行されてしまいます。これが非常に重いのです。
そこで、以下のようにすると速くすることができます。

var doc = document;

document; // こっちより
doc;      // こっちのが速い

これだけでも、大丈夫なのですが、今まで document を使って書いてきたコードをすべて書き換えるのはめんどくさいですよね。
ですので

var doc = document;
var document = doc;

のようなことを出来れば一番いいのですが。。。
これもまた、 JavaScript では変数はスコープの先頭で生成されるため、 document は空の変数となり undefined になってしまいます。
そこでさらに以下のようにします。

var doc = document;
eval('var document = doc');

evalvar 宣言することでスコープ途中から変数を生成することができるのです。
これで、以降の document は内部メソッドを呼ばれずに変数としてアクセスできます。
最後に、 IE でしか効果ないので条件付きコメントで囲っておきましょう

/*@cc_on 
var doc = document;
eval('var document = doc');
@*/

はい。完成。わーわーぱちぱちぱち

まとめ

これは便利!使ってください!

追記:

なんか、すごい勢いでブクマされてるのでびっくりしつつ追記。
以下のようにすると document 以外のグローバル変数にも使えます。そして、それぞれに同じ効果があります。

/*@cc_on
eval((function(props) {
  var code = [];
  for (var i = 0 l = props.length;i<l;i++){
    var prop = props[i];
    window['_'+prop]=window[prop];
    code.push(prop+'=_'+prop)
  }
  return 'var '+code.join(',');
})('document self top parent alert setInterval clearInterval setTimeout clearTimeout'.split(' ')));
@*/

追記2:

さらにの反響に驚愕しつつ追記><

この方法は document と書かれた部分を 5 倍以上(ループのコストを引くとたぶん 10 倍以上?)速くすることができるのですが、その数倍というのは「プロパティアクセス」と「関数呼び出し」の差です(関数呼び出しを減らしていると考えてください)。
ですので、ほとんどのウェブサイトでは効果はあまり感じられないかもしれません
ただ、僕の作ってるものですごい効果があったので、焦ってブログに書いてしまいました。もうちょっと注意深くエントリを書くべきだったかもしれないですね><

参照:
一行で IE の JavaScript を高速化する方法 - #生存戦略 、それは - subtech
mala on Twitter: "amachangのあれ、すごいブクマされてるけど10万回ループして0.5秒みたいな話だからね。試しにLDRのツリー描画部分のベンチ取ってみたけど全く速くならなかった。"

しかし、この方法は document だけに適用できる方法ではありません。ありとあらゆる DOM アクセスに対して同様のテクニック、考え方を応用することができます。応用すれば、多くのサイトで JS の高速化が出来るのではないかと思います。
そこら辺の内容はそのうち書きます。

お騒がせしました><