Array かどうかを判定するいくつかの方法について

この日記はご指摘を元に再構成したものです。
昨日の続きです。

jQuery1.3で、isArray や isFunction の処理が差し替えられています。
IE6で発生するメモリリークを回避するためのようです。

isArray や isFunction などは基本的なロジックであり、かつjQueryはブラウザを意識したコードの切り分けを行っていないので、速度が気がかりです。

TEST IE6 IE8 Firefox3 Firefox3.1(JIT) Safari3 Chrome1(JIT) Opera10α
Array#Object.prototype.toString.call 2609 1311 878 947 2063 822 1719
notArray#Object.prototype.toString.call 2672 1872 1642 923 1953 366 2016
"length" in array 797 639 279 40 469 153 359
"length" in notarray 828 1419 304 79 500 185 328
Array#instanceof 922 702 477 366 547 42 391
notArray#instanceof 937 858 486 382 531 42 391

スコアは、id:os0x さんのソースに、"length" in array を追加したもので計りました(文末参照)。
# os0x さん、いつもありがとうございます。

今後は改善されるかもしれませんが、

var toString = Object.prototype.toString;
function isArray(array) {
  return (toString.call(array) === "[object Array]");
}

としてしまうと、array instanceof Array に比べ、2〜20倍遅くなるようです。

ソース

よりjQueryの実装に近づけるために、var toString = Object.prototype.toString; を追加しています。

<html>
<body>
<script type="text/javascript">
var array = [];
var notarray = {};
(function(){
var S = new Date*1;
var toString = Object.prototype.toString;
for (var i = 0; i < 1000000;i++){ ( toString.call(array) === "[object Array]" ) }
document.write('Array#Object.prototype.toString.call : ' + (new Date-S) + '<br>');
})();
(function(){
var S = new Date*1;
var toString = Object.prototype.toString;
for (var i = 0; i < 1000000;i++){ ( toString.call(notarray) === "[object Array]" ) }
document.write('notArray#Object.prototype.toString.call : ' + (new Date-S) + '<br>');
})();
(function(){
var S = new Date*1;
for (var i = 0; i < 1000000;i++){ ( "length" in array ) }
document.write('"length" in array : ' + (new Date-S) + '<br>');
})();
(function(){
var S = new Date*1;
for (var i = 0; i < 1000000;i++){ ( "length" in notarray ) }
document.write('"length" in notarray : ' + (new Date-S) + '<br>');
})();
(function(){
var S = new Date*1;
for (var i = 0; i < 1000000;i++){ (array instanceof Array) }
document.write('Array#instanceof : ' + (new Date-S) + '<br>');
})();
(function(){
var S = new Date*1;
for (var i = 0; i < 1000000;i++){ (notarray instanceof Array) }
document.write('notArray#instanceof : ' + (new Date-S) + '<br>');
})();
</script>