今天刚回家,QQ群里就看到有人求助优化一段jQuery代码,简单看了一下,发现如果对jQuery这东西只停留在用的层面,而不知其具体实现的话,真的很容易用出问题来。这也是为什么近期我一直不怎么推崇用jQuery,这框架的API设定就有误导人们走上歧途之嫌。
需要优化的代码大致是这样的,也不方便直接把人家的代码复制过来,就大概地表达下意思:
$.fn.beautifyTable = function(options) { //定义默认配置项,再用options覆盖 return this.each(function() { var table = $(this), tbody = table.children('tbody'), tr = tbody.children('tr'), th = tbody.children('th'), td = tbody.children('td'); //单独内容的class table.addClass(option.tableClass); th.addClass(options.headerClass); //1 td.addClass(options.cellClass); //2 //奇偶行的class tbody.children('tr:even').addClass(options.evenRowClass); //3 tbody.children('tr:odd').addClass(options.oddRowClass); //4 //对齐方式 tr.children('th,td').css('text-align', options.align); //5 //添加鼠标悬浮 tr.bind('mouseover', addActiveClass); //6 tr.bind('mouseout', removeActiveClass); //7 //点击变色 tr.bind('click', toggleClickClass); //8 }); }; |
总的来说,这段代码不错,思路清晰,逻辑明确,想要做什么也通过注释说得很明白了。但是按作者的说法,当表格中有120行时,IE已经反映脚本运行时间过长了。显然从表现来看,这个函数的效率不高,甚至说极其低下。
寻找原因
于是,开始从代码层面进行分析,这是一个标准的jQuery插件式的函数,有个典型的return this.each(function() { ... };);形式的代码,如果作者写下这段代码的时候,不是照本宣科不经思考的话,就应该意识到jQuery的一个函数干了什么事。
简单来说,jQuery.fn下的函数,绝大部分是一个each的调用,所谓each,自然是对选择出来的元素进行了遍历,并对某个元素进行了指定的操作。那么看看上面一段代码,进行了多少的遍历,在此就假设只选择了120行,每一行有6列,另加上1行的表头吧:
● 遍历th,添加headerClass,元素数为6。
● 遍历td,添加cellClass,元素数为6*120=720。
● 从所有tr中找出奇数的,需要对所有tr进行一次遍历,元素数为120。
● 遍历奇数的tr,添加evenRowClass,元素数为120/2=60。
● 从所有tr中找出偶数的,需要对所有tr进行一次遍历,元素数为120。
● 遍历偶数的tr,添加oddRowClass,元素数为120/2=60。
● 遍历所有th和td,添加text-align,元素数为120*6+6=726。
● 遍历所有tr,添加mouseover事件,元素数为120。
● 遍历所有tr,添加mouseout事件,元素数为120。
● 遍历所有tr,添加click事件,元素数为120。