Ways to dereference a delimited property string

JavaScript performance comparison

Revision 3 of this test case created by James Wilkins

Preparation code


      
      <script>
Benchmark.prototype.setup = function() {
  function getValue1(s, o) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, ''); // strip a leading dot
    var a = s.split('.');
    while (a.length) {
      var n = a.shift();
      if (n in o) {
        o = o[n];
      } else {
        return;
      }
    }
    return o;
  }
  
  function getValue2(s, o) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, ''); // strip a leading dot
    var a = s.split('.').reverse();
    while (a.length) {
      var n = a.pop();
      if (n in o) {
        o = o[n];
      } else {
        return;
      }
    }
    return o;
  }
  
  function getValue3(path, origin) {
    if (origin === void 0 || origin === null) origin = self ? self : this;
    if (typeof path !== 'string') path = '' + path;
    var parts = path.split(/\[|\]|\.|'|"/g).reverse(),
      name; // (why reverse? because it's usually faster to pop off the end of an array)
    while (parts.length) {
      name = parts.pop();
      if (name) origin = origin[name];
    }
    return origin;
  }
  
  function getValue4(path, origin) {
    if (origin === void 0) origin = self ? self : this;
    if (typeof path !== 'string') path = '' + path;
    var c = '',
      pc,
      i = 0,
      n = path.length,
      name = '';
    if (n)
      while (i <= n) {
        ((c = path[i++]) == '.' || c == '[' || c == ']' || c == void 0) ? (name ? (origin = origin[name], name = '') : (pc == '.' || pc == '[' || pc == ']' && c == ']' ? i = n + 2 : void 0), pc = c) : name += c;
      }
    if (i == n + 2) throw "Invalid path: " + path;
    return origin;
  }
  
  function getValue5(path, origin) {
    if (origin === void 0 || origin === null) origin = self ? self : this;
    if (typeof path !== 'string') path = '' + path;
    var c, pc, i = 0,
      n = path.length,
      name = '',
      q;
    while (i <= n)
      ((c = path[i++]) == '.' || c == '[' || c == ']' || c == "'" || c == '"' || c == void 0) ? (c == q && path[i] == ']' ? q = '' : q ? name += c : name ? (origin ? origin = origin[name] : i = n + 2, name = '') : (pc == '[' && (c == '"' || c == "'") ? q = c : pc == '.' || pc == '[' || pc == ']' && c == ']' || pc == '"' || pc == "'" ? i = n + 2 : void 0), pc = c) : name += c;
    if (i == n + 2 || name) throw "Invalid path: " + path;
    return origin;
  }
  
  var o = {
    a: {
      b: {
        0: 0,
        1: {
          x: 1
        },
        2: 2
      }
    }
  }

};
</script>

Test runner

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

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
Using Regex
getValue1("a.b[1].x", o);
pending…
Using Regex - reversed parts
getValue2("a.b[1].x", o);
pending…
Split, reverse, and skip logic
getValue3("a['b'][1].x", o);
pending…
Low level string scan/parse
getValue4("a.b[1].x", o);
pending…
Low level string scan/parse with quotes support
getValue5("a['b'][1].x", o);
pending…
Just for comparison 1
eval("o.a.b[1].x")
pending…
Just for comparison 2
Function("return arguments[0].a.b[1].x")(o)
pending…

Compare results of other browsers

Revisions

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

0 Comments