新选择器querySelector家族的一些研究
第一个大问题:
拜读大神之后有一段话很值得玩味:
To clarify, the return value is actually a NodeList with all of the expected properties and methods, but its underlying implementation acts as a snapshot of elements rather than a dynamic query that is constantly reexecuted against a document. This implementation eliminates most of the performance overhead associated with the use of NodeList objects.
冒昧翻译:
需要强调下,返回值(querySelectorAll的)的确是带有所有期望的属性和方法的Nodelist。但是它的底层实现是一个元素的快照,而并非一个不断对document进行重复执行的动态查询。这个实现消除了大部分与Nodelist对象的使用相关的性能开销。
这句话作何理解呢?!为此写了一个Demo,直接看DEMO
代码中,分别用querySelectorAll和getElementsByTagName分别获取body下面的div元素,然后先后两次在第一个元素前面插入一个新的div。
然后观察之前查询结果中的length的值和第一个元素的变化。
结论是query的结果始终都是一个值,一直都没有变;而get结果的值却会随着每次的操作变化而变化。
这时候再来理解上面说的快照和动态查询,query就对应着是快照,一旦查询,之后再怎么变都与我无关;get就对应的是动态查询,会随着document的变化而变化。
第二个大问题:性能问题
写了一个Demo,两个方法同时查询一个ID为test的div,各自执行5000次。反复刷新5次,取平均值。
手机端谷歌浏览器:
Get | Query | 差值 | |
第1次 | 25 | 12 | 13 |
第2次 | 9 | 13 | -4 |
第3次 | 11 | 18 | -7 |
第4次 | 77 | 26 | 51 |
第5次 | 13 | 26 | -13 |
总计 | 135 | 85 | 50 |
平均下来每次运算get要比query慢10(ms),并且get方法在谷歌浏览器上面变现的不是很稳定,安卓默认浏览器也有类似的表现。
手机端UC浏览器:
Get | Query | 差值 | |
第1次 | 5 | 163 | -158 |
第2次 | 6 | 147 | -141 |
第3次 | 5 | 138 | -133 |
第4次 | 5 | 142 | -137 |
第5次 | 5 | 158 | -153 |
总计 | 26 |
算了平均值不统计了,结论很明显Query的性能要比get差很多。
看来在UC浏览器上还是不要使用Query了,性能差距太大了。