Looping through array or obect for VS forEach

Benchmark created by Daniel on


Description

As part of deep object cloning code we loop over props of object (Object, or Array) for-in is known to pickup non-itsOwnProperty keys, so testing with Object.keys(o).forEach(

Setup

// Object.keys shim.
    if(!Object.keys) Object.keys = function(o){  
     if (o !== Object(o))  
          throw new TypeError('Object.keys called on non-object');  
     var ret=[],p;  
     for(p in o) if(Object.prototype.hasOwnProperty.call(o,p)) ret.push(p);  
     return ret;  
    } 
    
    // Array.prototype.forEach shim.
    // Production steps of ECMA-262, Edition 5, 15.4.4.18
    // Reference: http://es5.github.com/#x15.4.4.18
    if ( !Array.prototype.forEach ) {
    
      Array.prototype.forEach = function( callback, thisArg ) {
    
        var T, k;
    
        if ( this == null ) {
          throw new TypeError( " this is null or not defined" );
        }
    
        // 1. Let O be the result of calling ToObject passing the |this| value as the argument.
        var O = Object(this);
    
        // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
        // 3. Let len be ToUint32(lenValue).
        var len = O.length >>> 0; // Hack to convert O.length to a UInt32
    
        // 4. If IsCallable(callback) is false, throw a TypeError exception.
        // See: http://es5.github.com/#x9.11
        if ( {}.toString.call(callback) != "[object Function]" ) {
          throw new TypeError( callback + " is not a function" );
        }
    
        // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
        if ( thisArg ) {
          T = thisArg;
        }
    
        // 6. Let k be 0
        k = 0;
    
        // 7. Repeat, while k < len
        while( k < len ) {
    
          var kValue;
    
          // a. Let Pk be ToString(k).
          //   This is implicit for LHS operands of the in operator
          // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
          //   This step can be combined with c
          // c. If kPresent is true, then
          if ( k in O ) {
    
            // i. Let kValue be the result of calling the Get internal method of O with argument Pk.
            kValue = O[ k ];
    
            // ii. Call the Call internal method of callback with T as the this value and
            // argument list containing kValue, k, and O.
            callback.call( T, kValue, k, O );
          }
          // d. Increase k by 1.
          k++;
        }
        // 8. return undefined
      };
    }
    
    // clone method A
    Object.prototype.cloneA = function() {
        var fn = function (o, cloner){
            if(o == null || typeof(o) != 'object') return o
            var no = new o.constructor()
            for(var key in o) no[key] = cloner(o[key], cloner) 
            return no;
        }
        return fn(this, fn)
    }
    // clone method B
    Object.prototype.cloneB = function() {
        var fn = function (o, cloner){
            if(o == null || typeof(o) != 'object') return o
            var no = new o.constructor()
            Object.keys(o).forEach(function(e){this[e] = cloner(o[e], cloner)},no) 
            return no;
        }
        return fn(this, fn)
    }
    
    var o = {a:'a',b:true,c:[1,2,3]}

Test runner

Ready to run.

Testing in
TestOps/sec
ForIn
var oA = o.cloneA()
 
ready
forEach
var oA = o.cloneB()
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Daniel on