Skip to content

Commit 14c0db9

Browse files
author
Rebecca Murphey
committed
perf nuggets
1 parent f633d1e commit 14c0db9

12 files changed

+313
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Cache Length During Loops
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
Touching the DOM comes at a cost; if you're adding a lot of elements to the
9+
DOM, do it all at once, not one at a time.
10+
11+
// this is bad
12+
$.each(myArray, function(i, item) {
13+
var newListItem = '<li>' + item + '</li>';
14+
$('#ballers').append(newListItem);
15+
});
16+
17+
// better: do this
18+
var frag = document.createDocumentFragment();
19+
20+
$.each(myArray, function(i, item) {
21+
var newListItem = '<li>' + item + '</li>';
22+
frag.appendChild(newListItem);
23+
});
24+
$('#ballers')[0].appendChild(frag);
25+
26+
// or do this
27+
var myHtml = '';
28+
29+
$.each(myArray, function(i, item) {
30+
html += '<li>' + item + '</li>';
31+
});
32+
$('#ballers').html(myHtml);
33+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Beware Anonymous Functions
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
Anonymous functions bound everywhere are a pain. They're difficult to debug,
9+
maintain, test, or reuse. Instead, use an object literal to organize and name
10+
your handlers and callbacks.
11+
12+
// BAD
13+
$(document).ready(function() {
14+
$('#magic').click(function(e) {
15+
$('#yayeffects').slideUp(function() {
16+
// ...
17+
});
18+
});
19+
20+
$('#happiness').load(url + ' #unicorns', function() {
21+
// ...
22+
});
23+
});
24+
25+
// BETTER
26+
var PI = {
27+
onReady : function() {
28+
$('#magic').click(PI.candyMtn);
29+
$('#happiness').load(PI.url + ' #unicorns', PI.unicornCb);
30+
},
31+
32+
candyMtn : function(e) {
33+
$('#yayeffects').slideUp(PI.slideCb);
34+
},
35+
36+
slideCb : function() { ... },
37+
38+
unicornCb : function() { ... }
39+
};
40+
41+
$(document).ready(PI.onReady);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Cache Length During Loops
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
In a for loop, don't access the length property of an array every time; cache
9+
it beforehand.
10+
11+
var myLength = myArray.length;
12+
13+
for (var i = 0; i < myLength; i++) {
14+
// do stuff
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Clever Conditionals
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
// old way
9+
if (type == 'foo' || type == 'bar') { ... }
10+
11+
// better
12+
if (/^(foo|bar)$/.test(type)) { ... }
13+
14+
// object literal lookup
15+
if (({ foo : 1, bar : 1 })[type]) { ... }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Detach Elements to Work with Them
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
The DOM is slow; you want to avoid manipulating it as much as possible. jQuery
9+
introduced `$.fn.detach` in version 1.4 to help address this issue, allowing you
10+
to remove an element from the DOM while you work with it.
11+
12+
var $table = $('#myTable');
13+
var $parent = $table.parent();
14+
15+
$table.detach();
16+
// ... add lots and lots of rows to table
17+
$parent.append(table);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Don't Act on Absent Elements
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
jQuery won't tell you if you're trying to run a whole lot of code on an empty
9+
selection — it will proceed as though nothing's wrong. It's up to you to verify
10+
that your selection contains some elements.
11+
12+
// BAD: this runs three functions
13+
// before it realizes there's nothing
14+
// in the selection
15+
$('#nosuchthing').slideUp();
16+
17+
// Better
18+
var $mySelection = $('#nosuchthing');
19+
if ($mySelection.length) { $mySelection.slideUp(); }
20+
21+
// BEST: add a doOnce plugin
22+
jQuery.fn.doOnce = function(func){
23+
this.length && func.apply(this);
24+
return this;
25+

}
26+
27+

$('li.cartitems').doOnce(function(){

28+
// make it ajax! \o/

29+
});
30+
31+
This guidance is especially applicable for jQuery UI widgets, which have a lot
32+
of overhead even when the selection doesn't contain elements.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Keep Things DRY
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
Don't repeat yourself; if you're repeating yourself, you're doing it wrong.
9+
10+
// BAD
11+
if ($eventfade.data('currently') != 'showing') {
12+
$eventfade.stop();
13+
}
14+
15+
if ($eventhover.data('currently') != 'showing') {
16+
$eventhover.stop();
17+
}
18+
19+
if ($spans.data('currently') != 'showing') {
20+
$spans.stop();
21+
}
22+
23+
// GOOD!!
24+
var $elems = [$eventfade, $eventhover, $spans];
25+
$.each($elems, function(i,elem) {
26+
if (elem.data('currently') != 'showing') {
27+
elem.stop();
28+
}
29+
});
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Use Event Delegation
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
Event delegation allows you to bind an event handler to one container element
9+
(for example, an unordered list) instead of multiple contained elements (for
10+
example, list items). jQuery makes this easy with `$.fn.live` and `$.fn.delegate`.
11+
Where possible, you should use `$.fn.delegate` instead of `$.fn.live`, as it
12+
eliminates the need for an unnecessary selection, and its explicit context (vs.
13+
`$.fn.live`'s context of document) reduces overhead by approximately 80%.
14+
15+
In addition to performance benefits, event delegation also allows you to add
16+
new contained elements to your page without having to re-bind the event
17+
handlers for them as they're added.
18+
19+
// bad (if there are lots of list items)
20+
$('li.trigger').click(handlerFn);
21+
22+
// better: event delegation with $.fn.live
23+
$('li.trigger').live('click', handlerFn);
24+
25+
// best: event delegation with $.fn.delegate
26+
// allows you to specify a context easily
27+
$('#myList').delegate('li.trigger', 'click', handlerFn);
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Optimize Selectors
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
Selector optimization is less important than it used to be, as more browsers implement document.querySelectorAll() and the burden of selection shifts from jQuery to the browser. However, there are still some tips to keep in mind.
9+
10+
## ID-Based Selectors
11+
12+
Beginning your selector with an ID is always best.
13+
14+
// fast
15+
$('#container div.robotarm');
16+
17+
// super-fast
18+
$('#container').find('div.robotarm');
19+
20+
The `$.fn.find` approach is faster because the first selection is handled
21+
without going through the Sizzle selector engine — ID-only selections are
22+
handled using `document.getElementById()`, which is extremely fast because it is
23+
native to the browser.
24+
25+
## Specificity
26+
27+
Be specific on the right-hand side of your selector, and less specific on the
28+
left.
29+
30+
// unoptimized
31+
$('div.data .gonzalez');
32+
33+
// optimized
34+
$('.data td.gonzalez');
35+
36+
Use `tag.class` if possible on your right-most selector, and just tag or just
37+
`.class` on the left.
38+
39+
## Avoid excessive specificity.
40+
41+
$('.data table.attendees td.gonzalez');
42+
43+
// better: drop the middle if possible
44+
$('.data td.gonzalez');
45+
46+
A "flatter" DOM also helps improve selector performance, as the selector engine
47+
has fewer layers to traverse when looking for an element.
48+
49+
## Avoid the Universal Selector
50+
51+
Selections that specify or imply that a match could be found anywhere can be
52+
very slow.
53+
54+
$('.buttons > *'); // extremely expensive
55+
$('.buttons').children(); // much better
56+
57+
$('.gender :radio'); // implied universal selection
58+
$('.gender *:radio'); // same thing, explicit now
59+
$('.gender input:radio'); // much better
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Don't Treat jQuery as a Black Box
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
Use the source as your documentation — bookmark
9+
[http://bit.ly/jqsource](http://bit.ly/jqsource) and refer to it often.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Use Stylesheets for Changing CSS on Many Elements
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
If you're changing the CSS of more than 20 elements using `$.fn.css`, consider
9+
adding a style tag to the page instead for a nearly 60% increase in speed.
10+
11+
// fine for up to 20 elements, slow after that
12+
$('a.swedberg').css('color', '#asd123');
13+
$('<style type="text/css">a.swedberg { color : #asd123 }</style>')
14+
.appendTo('head');
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
chapter : performance
3+
section: 0
4+
title: Variable Definition
5+
attribution: jQuery Fundamentals
6+
---
7+
8+
Variables can be defined in one statement instead of several.
9+
10+
// old & busted
11+
var test = 1;
12+
var test2 = function() { ... };
13+
var test3 = test2(test);
14+
15+
// new hotness
16+
var test = 1,
17+
test2 = function() { ... },
18+
test3 = test2(test);
19+
20+
In self-executing functions, variable definition can be skipped all together.
21+
22+
(function(foo, bar) { ... })(1, 2);

0 commit comments

Comments
 (0)