JQuery Sucks (Live版) —— 记一次20min的优化
这篇黑的有点丧心病狂了,其实问题基本上都在我自己。但光看结果的话,确实可以总结为:因为替换了一个jquery的方法调用,一下子把1.8s的执行时间优化到了18ms。
1.8s的方法原来是长这个样子的:
function recur($this, $arr) {
if (blahblah) {
return $arr;
}
else{
return recur($this.next(), $arr.add($this));
}
}
recur($whatever, $());
思路很简单,就是递归查找,中标的元素放到结果集里。开始想用[]
来做结果集的,但随手搜了一下,发现jquery有个add的api,似乎用起来灰常爽的样子(后面的处理就直接可以在$arr
上.
了),毫不犹豫的构造了个jquery大对象出来(潜意识觉得会慢,但又觉得不会慢到哪里去)。
跑了一下,WTF,1.8s!count一下,总用就500个dom的样子,这不科学!打开chrome profile,果然是recur方法占了大部分时间,再展开一看有个叫xxxDomComparexxx
的function似乎是罪魁祸首。等等,为啥会有dom比较?
看了代码,问题就出在了jquery.add
上,因为jquery会保证如果是包装的是一个dom集合的话,里面的元素一定是唯一的。所以,每add一个对象进去,都会触发一次uniquesort,复杂度N一下子就成了N*M(Sizzle.uniqueSort的复杂度不会算 =.=)。
该回[]
:
function recur($this, arr) {
if (blahblah) {
return arr;
}
else{
arr.push($this);
return recur($this.next(), arr);
}
}
recur($whatever, []);
18ms搞定。
本着科学务实的精神,我还有个进一步的猜想:是不是dom元素的==
会比普通的==
更慢?测试结果如下http://jsperf.com/dom-equal。
慢,但根本没慢多少。
反正都是jq的错,黑完收工。