Skip to content

Instantly share code, notes, and snippets.

@cowboy
Forked from rmurphey/gist:3086328
Created July 10, 2012 23:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cowboy/3086861 to your computer and use it in GitHub Desktop.
Save cowboy/3086861 to your computer and use it in GitHub Desktop.
What's wrong with Netmag's "Optimize your JavaScript" post

What's wrong with Netmag's "Optimize your JavaScript" post

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).

Things that are just plain wrong

  • 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 a for 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 as for(...) { 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 a for loop is typically no faster (and sometimes slower) in Chrome. Making it faster in Firefox doesn't make it magically "faster" everywhere.

Things that demonstrate a lack of actual expertise in the subject matter

  • 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.

  • 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.

In Summary

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 :)

@CycoDawg
Copy link

Well I know I am maybe opening myself up here But this is very interesting, i dont read very much any more I knew a little bit of coding and html stuff But nothing really significant and I admit i have forgotten whatever it was i did know not much call for all that in My Occupation, This was fascinating and couldn't stop reading seems pretty blatant and responsible of the Author....I just think it should be said You All did a very good Job I dont know but I dont see it on here anywhere

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment