Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

JavaScript performance: Array.prototype versus []

DZone's Guide to

JavaScript performance: Array.prototype versus []

· Web Dev Zone ·
Free Resource

Jumpstart your Angular applications with Indigo.Design, a unified platform for visual design, UX prototyping, code generation, and app development.

Array.prototype contains many generic methods that can be applied to array-like objects. [] is a popular shortcut for accessing these methods. This post examines the pros and cons of using that shortcut.

Update: Inspired by a comment from Kevin Roberts, I’ve added a third way of accessing generic methods, and a conclusion.

Explanations

Array-like objects. Some objects in JavaScript are array-like, they have indexed access and a length property like arrays, but none of the array methods. Array-like objects include the special variable arguments (giving indexed access to all arguments that were passed to a function) and most DOM results. Not having the standard array methods is especially unfortunate under ECMAScript 5, which has goodies such as Array.prototype.forEach.

Generic methods. Some methods are generic. While they are directly available to instances of their prototype, they can also be borrowed by other instances. To borrow a generic method, one invokes one of the following two methods on it:

  • Function.prototype.call(thisValue, [arg1], [arg2], ...)
  • Function.prototype.apply(thisValue, [arrayWithArguments])
The borrowing instance is the first argument and becomes the value of this. Generic methods have to be written so that they require this to only have a minimal set of methods. For example, most generic array methods only need this to provide length and indexed access. Array.prototype.slice is generic and allows one to turn any part of an array-like object into an array.

Example: invoking Array.prototype.map() generically, on the array-like arguments object.

    function prefixHello(prefix) {
        return Array.prototype.map.call(arguments, function(elem) {
            return "Hello "+elem;
        });
    }
Interaction:
    > prefixHello("Jane", "John")
    [ 'Hello Jane', 'Hello John' ]

[] as a shortcut. [].foo is often used as a shortcut for Array.prototype.foo. That is, you access a prototype property via an instance.

  • Pro: More compact.
  • Con: Does not really describe one’s intent. You are not trying to invoke an instance method, you are borrowing a function from the prototype.
  • Con: Slightly slower (see below).

Timing several ways of accessing generic methods

I wanted to see how bad performance really suffered and did a quick non-scientific test. Test framework:
    var iterations = 100000000;
    var data = []; // empty so that slice() doesn’t have much to do
    (function () {
        var start = (new Date).getTime();
        
       // loop

        var diff = (new Date).getTime() - start;
        console.log(diff);    
    }());
Timing prototype access:
    for(var i=0; i<iterations; i++) {
        Array.prototype.slice.call(data);
    }
Timing the shortcut:
    for(var i=0; i<iterations; i++) {
        [].slice.call(data);
    }
Storing the prototype in a local variable:
    var arrayProto = Array.prototype;
    for(var i=0; i<iterations; i++) {
        arrayProto.slice.call(data);
    }
Results (iMac, 2.7 GHz Intel Core i5):

  iterations prototype shortcut quick prototype
Node.js 0.4.8 100,000,000 5019ms 5075ms 4692ms
Firefox 6 10,000,000 1592ms 2237ms 1522ms
Rhino 1.7 release 3 10,000,000 2318ms 2687ms 1878ms

Conclusion

The time differences are not exactly earth-shattering. Thus, unless you are working with performance-critical code, you should choose whatever you think reads best (as opposed to what is easiest to write).

 

From http://www.2ality.com/2011/08/array-prototype-performance.html

Take a look at the Indigo.Design sample applications to learn more about how apps are created with design to code software.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}