Javascript Performance Tips and Tricks
14 March 2012
A few conclusions from the slides of Thomas Fuchs' presentation at jsconf in 2009.
Literals are slightly faster than the classical notation.
This is weird stuff, but it works! The double bitwise operator (~~) is slightly faster than a "normal" parseInt.
The double bitwise operator can also be used as a better and faster alternative to Math.floor:
These two loops do exactly the same, but they are equally fast. And since the while loop has less code, that loop is "better".
By assigning the window object to a variable "w" before the loop, you cache the window object. This makes the script many times faster in almost all browsers. Only Safari handles both loops equally as fast. Firefox takes 1.44 seconds for the uncached version and 0.82 seconds for the cached version!
This "soSomething" function returns true or false. The first function first calculates 99 times 99 and then sees that the var f = false and then returns false. The second function first sees f is false and immediately returns false and doesn't calculate 99 times 99.
The second, tuned function is almost three times faster in Internet Explorer!
Both of these "doSomething" functions do the same, but the second function is nor only faster, but also easier to read and less code. One exception, namely Internet Explorer. IE is equally slow in both functions. So try to avoid with functions (altough it is a fucking cool function)
Literal vs. Classical notation
function classicalNotation() {
var array = new Array;
var object = new Object;
}
function literals() {
var array = [];
var object = {};
}
function evenShorter() {
var array = [], object = {};
}
var array = new Array;
var object = new Object;
}
function literals() {
var array = [];
var object = {};
}
function evenShorter() {
var array = [], object = {};
}
Literals are slightly faster than the classical notation.
parseInt vs. double bitwise magic
This is weird stuff, but it works! The double bitwise operator (~~) is slightly faster than a "normal" parseInt.
parseInt("12.5"); // result: 12
~~(1 * "1.25"); // result: 12.5
~~(1 * "1.25"); // result: 12.5
The double bitwise operator can also be used as a better and faster alternative to Math.floor:
~~undefined; // => 0
~~0; // => 0
~~[]; // => 0
~~{}; // => 0
~~(1/0); // => 0
~~false; // => 0
~~true; // => 1
~~1.2543; // => 1
~~4.9; // => 4
~~(-2.999); // => -2
~~0; // => 0
~~[]; // => 0
~~{}; // => 0
~~(1/0); // => 0
~~false; // => 0
~~true; // => 1
~~1.2543; // => 1
~~4.9; // => 4
~~(-2.999); // => -2
for-loop vs. while-loop
var test = '';
for (var i = 0; i < 10000; i++) {
test = test + string;
}
// versus:
var test = '', i = 0;
while(i <= 10000){
test = test + string
}
for (var i = 0; i < 10000; i++) {
test = test + string;
}
// versus:
var test = '', i = 0;
while(i <= 10000){
test = test + string
}
These two loops do exactly the same, but they are equally fast. And since the while loop has less code, that loop is "better".
Caching
for (var i = 0; i < 10000; i++) {
window.test = 'test';
}
// versus
var w = window;
for (var i = 0; i < 10000; i++) {
w.test = 'test';
}
window.test = 'test';
}
// versus
var w = window;
for (var i = 0; i < 10000; i++) {
w.test = 'test';
}
By assigning the window object to a variable "w" before the loop, you cache the window object. This makes the script many times faster in almost all browsers. Only Safari handles both loops equally as fast. Firefox takes 1.44 seconds for the uncached version and 0.82 seconds for the cached version!
Expression tuning
var f = false;
var n = 99;
function doSomething() {
return n*n && f;
}
function doSomething() {
return f && n*n; // do you see what we did there?
}
var n = 99;
function doSomething() {
return n*n && f;
}
function doSomething() {
return f && n*n; // do you see what we did there?
}
This "soSomething" function returns true or false. The first function first calculates 99 times 99 and then sees that the var f = false and then returns false. The second function first sees f is false and immediately returns false and doesn't calculate 99 times 99.
The second, tuned function is almost three times faster in Internet Explorer!
Avoid with() statements
function doSomething() {
var object = { title: 'title', desc: 'some text' };
with(object) {
var i = 10000;
while(i--) desc += 'some more text...<br />';
return desc;
}
}
function doSomething() {
var object = { title: 'title', desc: 'some text' }, i = 0;
while(i <= 10000) {
object.desc += 'some more text...<br />';
}
return object.desc;
}
var object = { title: 'title', desc: 'some text' };
with(object) {
var i = 10000;
while(i--) desc += 'some more text...<br />';
return desc;
}
}
function doSomething() {
var object = { title: 'title', desc: 'some text' }, i = 0;
while(i <= 10000) {
object.desc += 'some more text...<br />';
}
return object.desc;
}
Both of these "doSomething" functions do the same, but the second function is nor only faster, but also easier to read and less code. One exception, namely Internet Explorer. IE is equally slow in both functions. So try to avoid with functions (altough it is a fucking cool function)
You must have JavaScript enabled to use this form!
3 comments
New on Dreamdealer
Behind the scenes: CSS-only Clock
Intelligent image cropping with focal point
image-rendering: pixelated
Don't forget about inherit
Are you still using PX for font sizing?

igorski
21 August 2012Cool stuff Johannemans! Regarding the caching example surely you could cache the reference to the "test"-property ?
var t = window.test;
for (var i = 0; i < 10000; i++) {
t = 'test';
}
This avoids the unnecessary lookup of the property "test" in window, which happens upon each iteration of the loop, this way you can assign the value immediately to the cached reference.
Regaring what Christophe said, I believe it is to with the presented example of the for/while :
// versus:
var test = '', i = 0;
while(i <= 10000){
test = test + string
}
This won't actually loop and cause the JavaScript parser to get stuck in an infinite loop. (the "i" variable remains the same throughout the while loop as it is never incremented, thus ( while i <= 10000 ) will always return true.
You should add i++ in the loop.
On the subject, a while-loop grants an enormous performance boost over a for loop when it is used in REVERSE. I.e:
var i = 10000;
while ( i--)
{
test = test + string;
}
(note that the construction of the while-condition will automatically have it subtract a value of 1 upon each iteration). This works fine when parsing a load of data, for instance. Though some situations call for a rewrite of your logic as you're starting with the last item in a list, rather than the first.
Johan van Tongeren
27 June 2012What's the difference then? Please explain what you're trying to say.
Christophe
27 June 2012What a mistake to make !!!!!!!!!!!!!!
exactly the same ??????????
Back to scool !!!!!!!!
var test = '';
for (var i = 0; i < 10000; i++) {
test = test + string;
}
// versus:
var test = '', i = 0;
while(i <= 10000){
test = test + string
}