Update: The original post on Netmag has been updated since this was written.
I tweeted earlier that this should be retracted. Generally, these performance-related articles are essentially little more than linkbait -- there are perhaps an infinite number of things you should do to improve a page's performance before worrying about the purported perf hit of multiplication vs. division -- but this post went further than most in this genre: it offered patently inaccurate and misleading advice.
Here are a few examples, assembled by some people who actually know what they're talking about (largely Rick Waldron and Ben Alman, with some help from myself and several others from the place that shall be unnamed).
-
Calling
array.push()
five times in a row will never be a "performance improvement." The author has clearly confused creating an array literal["foo", "bar", "baz"]
and then using.join("")
on it vs. creating an array, pushing individual items, and then joining. See here for the proof, and see here for a possible explanation. -
The author sets up a
for
loop as follows:for(var i = 0; length = 999; i <= length; i++){
. This results in a syntax error. -
The author suggests
for(var i = my_array.length; i--)
as a shorter version of afor
loop. While you can get by with using the decrement as the conditional, omitting the semi-colon at the end causes a syntax error. Also, if someone were to move the semi colon to before the decrement, it would cause an infinite loop. Also, if you were ever to do this style of cleverness, a while loop looks much more sane:var i = my_array.length; while( i-- ) {}
. -
Because JavaScript lacks block scope, variables declared inside blocks are not local to any block. The variable declaration is actually "hoisted" to the beginning of the nearest execution context (function body or global scope) such that
var foo; for(...) { foo = 1; }
behaves exactly the same asfor(...) { var foo = 1; }
. It is, however, considered bad practice to declare variables inside of blocks, because novice JavaScript developers infer from it that JavaScript has block scope. -
Creating a variable to hold the
length
property in afor
loop is typically no faster (and sometimes slower) in Chrome. Making it faster in Firefox doesn't make it magically "faster" everywhere.
-
The article mentions DOM perf almost as an afterthought. When it comes to perf, rarely is JavaScript the problem -- DOM reflows are a much more likely culprit for performance issues, but even just modifying elements via the DOM API in memory is still slow. This is one of many reasons people use client-side templates, which the author does not mention. All of that said, if you're looking for real performance gains, take a long, hard look at your HTTP overhead. Chances are that optimizing an image or two will make more difference than any improvements you can make to your JavaScript.
-
The author talks about avoiding unnecessary method calls within conditionals, and then demonstrates by accessing a property, rather than calling a method.
-
The author talks about local vs global variables, and then proceeds to demonstrate the concept with an instance property, not a local variable.
-
The author uses the global
Array
constructor function to create a new array, rather than using the Array literal[]
syntax which is, itself, known to be a performance improvement. -
The section "Calling methods or properties on array elements" is true, but somewhat misses the point: lookups of any sort should be stored in a variable, rather than being repeated. This guidance has nothing to do with array elements; it's just as true for the result of a function call.
-
In the "encapsulating methods within class declarations" example, the author fails to point out that there are really 2 performance metrics to be tested: 1) cost while creating a new instance object and 2) cost while dereferencing a method from an instance object. The provided example only discusses #1 without addressing #2. What's interesting is that, typically, #1 and #2 are mutually exclusive. When methods are defined directly on an instance object, they consume more memory and cycles (because a new function object must be created for each instance object). When methods are defined on the prototype however, they must only be defined once, so the initial overhead is less, but each time the method is dereferenced from the instance object, the cost is slightly higher because the prototype chain must be traversed. A compromise can be had whereby a previously-defined function is defined as a method on each individual instance, thus reducing memory usage, but the cost of initially assigning the method probably won't offset the cost of accessing the method via the prototype down the road.
-
The "encapsulating methods within class declarations" section also lacks an understanding of semantic, language level behaviour and use cases for instance properties and methods, and prototype properties and methods. Comparing instance properties and methods with prototype properties and methods is like comparing a knife with a stealth fighter jet -- yes they can both be lethal, but one is far more efficient and suited to larger scale tasks and the other is suited to individual, "case by case" (ie. instance) tasks. Additionally, any time that data properties are defined on a prototype, it's likely a mistake that will result in bugs.
-
The section under the heading "Unnecessary method calls within conditionals in For Loops" gives an egregiously absurd example that itself misses the point that should've been made: operations in loops have costs, be mindful of this. In addition to this mistake, there is actually no such thing as a "conditional in For Loops"; the author is simply unaware that the actual name is "Expression", as in... IterationStatement, optional Expression.
-
The author advises using Firebug for profiling code, but provides absolutely zero guidance on how to do this, or even a link to any guidance. This article offers step-by-step guidance on using the Chrome developer tools to identify performance bottlenecks -- which, as we mentioned, you should only do after you've done a whole lot of other things you can do to improve your page's performance. The YSlow page offers a good list of things to do to improve page performance.
Smart people spent their time correcting this article, and this sucks. When misleading and inaccurate content gets published by a prominent site, it falls to a busy community to use its time -- a scarce resource -- to correct said content. Publications that distribute such content should be embarassed, and while authors who create it should perhaps be commended for their efforts, they should strongly consider enlisting a knowledgeable technical reviewer in the future. Goodness knows the publication won't cover their ass for them.
Want to know more? See some debunktastic perf tests :)
@JamieMason I ask again: can you please take the time to create a fork of this gist and adjust it to how you think it should have been stated? I appreciate the "be nice" advice, but I'd like to see how that would change this post. More to the point, I'd like to see people critical of this post -- which took a non-trivial amount of time to write -- spend a bit of time of their own to make it better, rather than just writing comments about how it should have been better.