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>