Home > Article > Web Front-end > Some optimization suggestions for jQuery performance_jquery
Don’t access the length property of the array every time in the loop, cache it before the loop starts:
var myLength = myArray.length; for (var i = 0; i < myLength; i++) { // do stuff }
Perform append operation outside the loop
Direct manipulation of DOM is very performance-intensive, especially do not directly manipulate DOM in a loop:
// 这样性能很差 $.each(myArray, function(i, item) { var newListItem = '<li>' + item + '</li>'; $('#ballers').append(newListItem); }); <p>// 这样性能较好<br />var frag = document.createDocumentFragment();</p><p>$.each(myArray, function(i, item) {<br /> var newListItem = '<li>' + item + '</li>';<br /> frag.appendChild(newListItem);<br />});<br />$('#ballers')[0].appendChild(frag);</p><p>// 这样也很好<br />var myHtml = '';</p><p>$.each(myArray, function(i, item) {<br /> html += '<li>' + item + '</li>';<br />});<br />$('#ballers').html(myHtml);</p>
Keep the code concise
Avoid doing repetitive things. If you keep doing the same thing, something might be wrong:
// 丑 if ($eventfade.data('currently') != 'showing') { $eventfade.stop(); } if ($eventhover.data('currently') != 'showing') { $eventhover.stop(); } if ($spans.data('currently') != 'showing') { $spans.stop(); } // 漂亮!! var $elems = [$eventfade, $eventhover, $spans]; $.each($elems, function(i,elem) { if (elem.data('currently') != 'showing') { elem.stop(); } });
Be wary of anonymous functions
It is very painful to have anonymous functions flying all over the place. They are difficult to debug, maintain, test or reuse. You should name the functions as much as possible and encapsulate them in objects to implement effective management:
// 不好 $(document).ready(function() { $('#magic').click(function(e) { $('#yayeffects').slideUp(function() { // ... }); }); $('#happiness').load(url + ' #unicorns', function() { // ... }); }); // 好 var PI = { onReady : function() { $('#magic').click(PI.candyMtn); $('#happiness').load(PI.url + ' #unicorns', PI.unicornCb); }, candyMtn : function(e) { $('#yayeffects').slideUp(PI.slideCb); }, slideCb : function() { ... }, unicornCb : function() { ... } }; $(document).ready(PI.onReady);
Optimization of selector
As more and more browsers support document.querySelectorAll(), the burden of the selector has slowly been transferred to the browser, but there are still some tips to pay attention to:
Prioritize and use ID selectors whenever possible:
// 快 $('#container div.robotarm'); // 相当快 $('#container').find('div.robotarm'); 使用 $.fn.find 的方式更快,因为在 $.fn.find 之前的选择器并没有使用 jQuery 自带的 Sizzle 选择器引擎,而是使用了浏览器 document.getElementById() 方法,浏览器原生的方法自然更快。 使用组合选择器时,尽可能使右端更明确,而左端不尽量不明确: // 未优化 $('div.data .gonzalez'); // 已优化 $('.data td.gonzalez');
Try to use tag.class on the right end of the selector, and only use tag or .class on the left end if possible.
Avoid being overly specific:
$('.data table.attendees td.gonzalez'); // 在不影响结果的情况下尽量删掉中间多余部分 $('.data td.gonzalez');
A concise DOM structure also helps improve the performance of the selector, because the selector may take fewer detours to find those elements.
Try to avoid using wildcards. Any explicit or implicit use of wildcards will reduce the performance of the selector:
$('.buttons > *'); // 极慢 $('.buttons').children(); // 好多了 $('.gender :radio'); // 隐式地使用通配符,慢 $('.gender *:radio'); // 显式地使用通配符,同上,慢 $('.gender input:radio'); // 嗯,快多了
Use event proxy
The event proxy allows an event to be bound to a container (such as an unordered list ul), rather than to all elements in the container (such as the list element li). Although $.fn.live and $.fn.delegate both bind events to the container, $.fn.delegate should be used as much as possible, after all, its clear context (compared to the context of $.fn.live document) is much smaller, avoiding a lot of unnecessary filtering.
In addition to performance improvements, if you add new elements to a container bound to an event, these new elements do not need to be bound to the event again, which is also an advantage.
// 不好 (如果列表元素非常多,你就悲剧了) $('li.trigger').click(handlerFn); // 好些:使用 $.fn.live 进行事件代理 $('li.trigger').live('click', handlerFn); // 最好:使用 $.fn.delegate 进行事件代理 // 因为这样可以明确的指定一个上下文 $('#myList').delegate('li.trigger', 'click', handlerFn);
Unload the element from the DOM and then operate it
DOM operations are relatively slow, so you should try to avoid directly operating DOM. jQuery introduced the $.fn.detach method in its version 1.4, which can unload elements from the DOM and then operate them. After the operation is completed, they can be added to the DOM:
var $table = $('#myTable'); var $parent = $table.parent(); $table.detach(); // ... 例如这里给表格添加了很多很多行 $parent.append(table);
Use external style sheets to modify styles for a large number of elements
When using $.fn.css to modify styles for more than 20 elements, you should consider adding style tags directly to the page, which is said to improve performance by 60%.
// 当元素少于 20 个时使用这个方法,多余 20 个时,速度就慢了 $('a.swedberg').css('color', '#asd123'); // 多余 20 个元素时,应考虑直接在页面中添加 style 标签 $('<style type="text/css">a.swedberg { color : #asd123 }</style>') .appendTo('head');
Use $.data instead of $.fn.data
Applying $.data to a DOM element is 10 times faster than calling $.fn.data directly on the selector. Of course, the premise is to first understand the difference between DOM elements and jQuery result sets.
// 速度一般 $(elem).data(key,value); // 速度提升 10 倍 $.data(elem,key,value);
Don’t waste time on empty elements
jQuery won’t actively tell you that you are running code on a blank result set – and no errors will occur during execution. So sometimes before executing the code, you need to first determine whether the result set is empty:
// 不好:执行了三个函数之后 // 才发现结果集上没有任何元素 $('#nosuchthing').slideUp(); // 好 var $mySelection = $('#nosuchthing'); if ($mySelection.length) { $mySelection.slideUp(); } // 最好:增加一个 doOnce 插件 jQuery.fn.doOnce = function(func){ this.length && func.apply(this); return this; } $('li.cartitems').doOnce(function(){ // 这里可以确保结果集不是空的 });
This approach is particularly useful for jQuery UI aspects, as the overhead can be significant even if the result set contains no elements.
Definition of variables
Multiple variables can be defined in one statement:
// 老掉牙的写法 var test = 1; var test2 = function() { ... }; var test3 = test2(test); // 新写法 var test = 1, test2 = function() { ... }, test3 = test2(test);
In self-executing functions, variables do not even need to be defined:
(function(foo, bar) { ... })(1, 2);
Conditional judgment
// 土方法 if (type == 'foo' || type == 'bar') { ... } // 较先进的方法 if (/^(foo|bar)$/.test(type)) { ... } // 使用对象查找 if (({ foo : 1, bar : 1 })[type]) { ... }