Recursive vs iterative object walk

JavaScript performance comparison

Test case created by Chris Hernandez

Preparation code

 
<script>
Benchmark.prototype.setup = function() {
    function isObject (thing) {
        return thing === Object(thing);
    }
   
    var data = {
      'alpha': {
        'chris': ['Truman', 'Toby'],
        'josie': ['Darwin', 'Bruce', 'Sadie'],
        'someone': {
          'billy': ['programming', 'designing', 'rocking'],
          'tom': {
            'ian': {
              'music': ['white stripes', 'black keys', 'britney spears'],
              'hobbies': ['running', 'jumping', 'swimming']
            }
          }
        }
      },
      'beta': {
        'portland': ['pigs', 'chickens'],
        'austin': {
          'round rock': ['conservative', 'cowboys'],
          'georgetown': ['stupid', 'annoying'],
          'south austin': ['cool', 'trendy']
        }
      }
    };
};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Iterative
function iterate(obj) {

  'use strict';

  var currentObj = obj;
  var currentKeys = Object.keys(obj).reverse();
  var nextKey = currentKeys.pop();
  var objStack = [];
  var keyStack = [];
  var padding = '';

  while (1) {

    var current = currentObj[nextKey];

    if (isObject(current)) {
      console.log(padding + nextKey); // visit
      objStack.push(currentObj);
      keyStack.push(currentKeys);
      currentKeys = Object.keys(current).reverse();
      currentObj = current;
      padding += '>';
    } else {
      console.log(current ? (padding + nextKey + ' : ' + currentObj[nextKey]) : 'stepping out...');
    }

    if (currentKeys.length) {
      nextKey = currentKeys.pop();
    } else {
      // console.log('done with current keys');
      if (keyStack.length) {
        currentKeys = keyStack.pop();
        currentObj = objStack.pop();
        nextKey = currentKeys.pop();
        padding = padding.substring(0, padding.length - 1);
      } else {
        // console.log('done with keyStack');
        // we're done?
        break;
      }
    }

  }

}

iterate(data);
pending…
Recursive
function recurse(data, padding) {

  var current;

  for (var key in data) {

    current = data[key];

    if (isObject(current)) {
      console.log(padding + key);
      padding += '>';
      recurse(current, padding);
      padding = padding.substring(0, padding.length - 1);
    } else {
      console.log(padding + ' : ' + current);

    }

  }

}

recurse(data);
pending…

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

Compare results of other browsers

0 comments

Add a comment