任意の引数の束縛2006年02月21日 03時00分

前回 JavaScript での引数束縛を扱った際には引数リストの先頭からの束縛だったが、ななしさんによる Array#splice を使った方法を応用すれば任意の引数の束縛も比較的簡単な形で書ける。C++ には bind1stbind2nd というのがあるそうだが、それと同じようなことができるわけだ。

Function.prototype.bindNth = function (/* n, arg, ... */) {
  var self = this;
  var args = arguments;
  args[0]--;
  Array.prototype.splice.call(args, 1, 0, 0);
  return function () {
    Array.prototype.splice.apply(arguments, args);
    return self.apply(this, arguments);
  };
};

function concat(a, b) {
  return "" + a + b;
}

alert( concat.bindNth(1, "a")("b") ); // "ab"
alert( concat.bindNth(2, "a")("b") ); // "ba"

length プロパティのパフォーマンス2006年02月21日 03時01分

for 文 2.0」(IT戦記) では length プロパティの評価をループの外に出すことにより高速化を図っています。DOM の NodeList オブジェクト (document.getElementsByTagName() などで取得) や HTMLCollection オブジェクト (document.forms などで取得) の length プロパティは「生きている」(オブジェクト取得後の操作が反映される) 、すなわち誤解を恐れずいえば評価のたびに数えなおす必要があるので遅いというのも納得ですが、JavaScript のネイティブオブジェクトである配列の length プロパティはどうなのでしょうか。実際に調べてみました。

以下は 10000 個の span 要素に対する NodeList オブジェクトと配列の length プロパティのパフォーマンスを調べた結果です。数値は 5 回テストした平均値で単位はミリ秒、「先に取得」というのは「for 文 2.0」で紹介されていたように length プロパティの評価を 1 回だけにした場合です。テストはいずれも Pentium M 1.3 GHz 、メモリ 256 MB 、Windows XP のマシン上で行いました。

length プロパティのパフォーマンス (単位: ms)
ブラウザ NodeList 配列 先に取得
Firefox 1.0.7 144 14 2
Firefox 1.5.0.1 144 12 4
IE 6.01 SP2 11062 14 2
Opera 7.54u2 54911 28 18
Opera 8.51 26 12 4
Opera 9 TP2 22 12 6

結果を見ればわかるとおり、NodeList と配列では length プロパティの評価に大きなパフォーマンスの差があります。length プロパティの評価を 1 回だけにするというのは NodeList に対しては有効ですが、配列に対してはよほど性能が求められる場合を除けば大きな意味はないのではというのが個人的な見解です。

それにしても Opera 7 は NodeList の length プロパティの評価が非常に遅いのですが Opera 8 以降では非常に速くなっています。何か特殊な最適化でも施してあるのでしょうか。