How DRY impacts JavaScript performance //
Faster JavaScript execution for the lazy developer
Mathias Bynens – Velocity Europe, November 2011
Slide 2
Slide 2 text
@mathias
Slide 3
Slide 3 text
JavaScript & performance
Rule #1: nothing to do with JS
Slide 4
Slide 4 text
JavaScript & performance
Slide 5
Slide 5 text
JavaScript & performance
What about
the actual run-time performance
on the client side?
Slide 6
Slide 6 text
DRY
flic.kr/p/2ZGCT
Slide 7
Slide 7 text
WET
flic.kr/p/5Jnj7Q
Slide 8
Slide 8 text
“DRY leads to readable,
maintainable code”
Slide 9
Slide 9 text
DRY JavaScript
improves
performance
…if you do it right
Slide 10
Slide 10 text
So, where to avoid
repetition?
Slide 11
Slide 11 text
What’s slow in JavaScript?
Slide 12
Slide 12 text
What’s slow in JavaScript?
1. The DOM
Slide 13
Slide 13 text
What’s slow in JavaScript?
1. The DOM
2. Function calls
Slide 14
Slide 14 text
What’s slow in JavaScript?
1. The DOM
2. Function calls
3. Lookups
Slide 15
Slide 15 text
DOM manipulation
// Create the element in memory
var el = document.createElement('p');
// Insert the element into the DOM
document.body.appendChild(el);
Slide 16
Slide 16 text
DOM manipulation
…
Slide 17
Slide 17 text
DOM manipulation
var div = document.createElement('div'),
p = document.createElement('p');
// Bad
document.body.appendChild(div);
div.appendChild(p);
Slide 18
Slide 18 text
DOM manipulation
var div = document.createElement('div'),
p = document.createElement('p');
// Better
div.appendChild(p);
document.body.appendChild(div);
Slide 19
Slide 19 text
DOM manipulation
…
Slide 20
Slide 20 text
DOM manipulation
var p = document.createElement('p'),
i = 4;
while (i--) { // Add four
elements
document.body.appendChild(p.cloneNode(false));
}
Slide 21
Slide 21 text
DOM manipulation
var frag = document.createDocumentFragment(),
p = document.createElement('p'),
i = 4;
while (i--) { // Add four
elements
frag.appendChild(p.cloneNode(false));
}
document.body.appendChild(frag);
Slide 22
Slide 22 text
Function calls
// Function declaration
function foo(bar) {
return bar;
}
// Function call
foo('something');
Slide 23
Slide 23 text
Function calls
alert('foo');
document.getElementById('foo');
$('#foo');
Slide 24
Slide 24 text
Function calls
$('.foo').show();
// other stuff…
$('.foo').hide();
Slide 25
Slide 25 text
Function calls
var $foo = $('.foo');
$foo.show();
// other stuff…
$foo.hide();
Slide 26
Slide 26 text
Function calls
var $foo = $('.foo').show();
// other stuff…
$foo.hide();
Property lookups
var foo = YAHOO.util.Dom.get('foo'),
bar = YAHOO.util.Dom.get('bar'),
baz = YAHOO.util.Dom.get('baz'),
qux = YAHOO.util.Dom.get('qux');
Slide 30
Slide 30 text
Property lookups
var get = YAHOO.util.Dom.get,
foo = get('foo'),
bar = get('bar'),
baz = get('baz'),
qux = get('qux');
Slide 31
Slide 31 text
Array item lookups
var elems = document.getElementsByTagName('p'),
length = elems.length;
while (length--) {
if (elems[length].className == 'foo') {
// do something with elems[length]
elems[length].innerHTML = 'LOLWAT';
}
}
Slide 32
Slide 32 text
Array item lookups
var elems = document.getElementsByTagName('p'),
length = elems.length,
elem;
while (length--) {
elem = elems[length];
if (elem.className == 'foo') {
// do something with elem
elem.innerHTML = 'LOLWAT';
}
}
Slide 33
Slide 33 text
Scope lookups
var foo = 42;
foo; // no scope lookup
Slide 34
Slide 34 text
Scope lookups
var foo = 42;
(function() {
foo; // one scope lookup
}());
// IIFE – see http://mths.be/iife
Slide 35
Slide 35 text
Scope lookups
var foo = 42;
(function() {
(function() {
foo; // two scope lookups
}());
}());
Slide 36
Slide 36 text
Scope lookups
Slide 37
Slide 37 text
Scope lookups
var foo = 42;
(function(foo) {
(function(foo) {
foo; // ZOMG, no scope lookups!!1
}(foo));
}(foo));
Slide 38
Slide 38 text
Scope lookups
Slide 39
Slide 39 text
Scope lookups
(function() {
// every time you use `window`
// or `document` here
// that’s a scope lookup
}());
Slide 40
Slide 40 text
Scope lookups
(function() {
var doc = document,
win = window;
// lookup once, then cache
}());
Slide 41
Slide 41 text
Scope lookups
(function(win, doc) {
// use `win` and `doc` here
// no scope lookups
// no performance penalty!
}(this, document));
Slide 42
Slide 42 text
Recap: what’s slow in JavaScript?
Slide 43
Slide 43 text
Recap: what’s slow in JavaScript?
1. The DOM
Slide 44
Slide 44 text
Recap: what’s slow in JavaScript?
1. The DOM
2. Function calls
Slide 45
Slide 45 text
Recap: what’s slow in JavaScript?
1. The DOM
2. Function calls
3. Lookups
Slide 46
Slide 46 text
Especially when used inside…
Slide 47
Slide 47 text
Especially when used inside…
• Loops
Slide 48
Slide 48 text
Especially when used inside…
• Loops
• Intervals
Slide 49
Slide 49 text
Especially when used inside…
• Loops
• Intervals
• Handlers for events that fire frequently
Slide 50
Slide 50 text
It happens to the best!
// Don’t do this:
$(window).scroll(function() {
$('.foo').something();
});
Slide 51
Slide 51 text
It happens to the best!
// Don’t do this:
$(window).scroll(function() {
$('.foo').something();
});
Slide 52
Slide 52 text
It happens to the best!
// Don’t do this:
$(window).scroll(function() {
$('.foo').something();
});
// See http://mths.be/azs
Slide 53
Slide 53 text
typeof performance != 'the whole story'
Slide 54
Slide 54 text
tips & tricks
(not really)
Slide 55
Slide 55 text
New objects
var obj = new Object();
obj.x = 42;
obj.y = 'foo';
obj.z = false;
Slide 56
Slide 56 text
New objects
var obj = {
'x': 42,
'y': 'foo',
'z': false
};
Slide 57
Slide 57 text
New arrays
var arr = new Array();
arr.push(42);
arr.push('foo');
arr.push(false);
Slide 58
Slide 58 text
New arrays
var arr = [
42,
'foo',
false
];
Slide 59
Slide 59 text
Avoid switch
switch(foo) {
case 'alpha':
// do X
break;
case 'beta':
// do Y
break;
default:
// do Z
break;
}
Slide 60
Slide 60 text
Avoid switch
var switchObj = {
'alpha': function() {
// do X
},
'beta': function() {
// do Y
},
'_default': function() {
// do Z
}
};
(switchObj.hasOwnProperty(foo) && switchObj[foo] || switchObj._default)(args);
Slide 61
Slide 61 text
Don’t use jQuery for everything
$('.foo').click(function() {
$(this).prop('id');
// same as this, before jQuery 1.6:
// $(this).attr('id');
// also `href`, `checked`, `value`…
});
Slide 62
Slide 62 text
Don’t use jQuery for everything
$('.foo').click(function() {
this.id;
this.href;
this.checked;
this.value;
// etc.
});
Slide 63
Slide 63 text
jQuery document ready
$(document).ready(function() {
// teh coads
});
jQuery document ready
(function() {
// move s to the bottom
// and just use an IIFE*
}());
// * unless you use .appendChild() / .innerHTML on document.documentElement or document.body: http://mths.be/ieoa