2行でJavaScriptを高速化する方法

id:amachangさんの

に対して、id:uupaaさんが

IE以外でも使える色々な方法を提案なさっています。でも、
「正直documentを_docに置き換えるの面倒><」
そこで、たかがreplace(/document/g, '_doc')の手間を惜しむ皆様のために用意した、2行でJavaScriptを高速化する方法がこちら:

  • script全体を(function(document){})(document)で囲む

これだね!

ベンチマーク

uupaaさんの記事にあるB系のソースを使わせていただきました。

ブラウザ B0 B1 B2 B3 B4 B5 b6
IE 6 10281 4938 10844 4672 4906 5203 6234
Firefox 3.0 628 - 676 324 357 400 493

SafariとかChromeとかOperaとか試してません……面倒くさがりなので!

ソース

<html><head><title>b6</title></head><body><script>
(function (document) {
  window.onload = function () {
    var begin = +new Date;
    job(1000000);
    alert(+new Date - begin);
  }
  function job(times) {
    for (var i = 0; i < times; ++i) {
      loop();
    }
  }
  function loop() {
    document;
  }
})(document)
</script></body></html>

それから、

  • function foo() {foo = function() {に置き換える

IEで速くなるよ! amachangさんの1行マジックに迫る速さだ! でも、

  • function foo() {window.foo = function() {に置き換える

と遅くなる! グローバルな定義はwindowオブジェクトのプロパティへの代入と同じだって聞いたことがあるのに、どうしてー!?

ブラウザ B0 B1 B2 B3 B4 B5 b6 b7 b8
IE 6 10281 4938 10844 4672 4906 5203 6234 5062 15062
Firefox 3.0 628 - 676 324 357 400 493 520 766
<html><head><title>b7</title></head><body><script>
(function (document) {
  window.onload = function () {
    var begin = +new Date;
    job(1000000);
    alert(+new Date - begin);
  }
  job = function(times) {
    for (var i = 0; i < times; ++i) {
      loop();
    }
  }
  loop = function() {
    document;
  }
})(document)
</script></body></html>
<html><head><title>b8</title></head><body><script>
(function (document) {
  window.onload = function () {
    var begin = +new Date;
    job(1000000);
    alert(+new Date - begin);
  }
  window.job = function(times) {
    for (var i = 0; i < times; ++i) {
      loop();
    }
  }
  window.loop = function() {
    document;
  }
})(document)
</script></body></html>

それでは皆様、良いお年を!

追記

はてなブックマークコメントのid:asiamothさん*1:

function 文(function foo() {})よりも function 式(var foo = function() {})という話は『The Good Parts』にも出てくるよ!

「The Good Parts」面白そうですね! ただ、前述の比較のキモはvar foo = function() {}ではなくfoo = function() {}でfooをグローバルに定義しているところです。元々は全体を無名関数で囲んでしまったことでfunction foo() {}で定義した関数を外から呼べなくなってしまうという問題への対処のつもりだったのですが、なぜか高速になってしまってびっくり、という……var foo = function() {}だと、少なくとも上の例の実行速度の面ではfunction foo() {}と同等です。