in operator

Benchmark created by WebReflection on


Description

Somebody asked for a benchmark here: http://webreflection.blogspot.com/2011/08/please-stop-reassigning-for-no-reason.html

However, the whole point is not about raw performances but implications that common patter to assign a potentially not defined property cause.

As example, consider it is not even possible to compare an object with a getter only since the common pattern will simply throw an Error during assignment.

obj.prop = // if no setter: ERROR

    obj.prop // getter

    || {}

;

With "prop" in obj everything would be still OK.

Preparation HTML

<script>
  // all functions should avoid JIT optimizations
  // (e.g. if nothing happens JIT may nullify function body)
  // hopefully assigning the object to a non GC global variable
  // will do the trick ... let's see ... 
  
  function inOperator(object) {
      "prop" in object || (object.prop = {});
      return object;
  }
  
  function commonPattern(object) {
      object.prop = object.prop || {};
      return object;
  }
  
  function betterPattern(object) {
      object.prop || (object.prop = {});
      return object;
  }
  
  var
      // simple shim that *should* fail in old browsers
      // if getters/setters are not supported
      defineProperty = Object.defineProperty || function (o, k, v) {
          o.__defineGetter__(k, v.get);
          o.__defineSetter__(k, v.set);
          return o;
      },
      globalResult
  ;
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
in operator set
globalResult = inOperator({});
ready
in operator
globalResult = inOperator({prop:{}});
ready
in operator + magic set
globalResult = inOperator(defineProperty({}, "prop", {
    get: function () {
        return this._prop;
    },
    set: function (_prop) {
        // here something more meaningful ...
        this._prop = _prop;
    }
}));
ready
in operator + magic
globalResult = inOperator(defineProperty({}, "prop", {
    get: function () {
        return this._prop || {}; // let's say the default
    },
    set: function (_prop) {
        // here something more meaningful ...
        this._prop = _prop;
    }
}));
ready
common pattern set
globalResult = commonPattern({});
ready
common pattern
globalResult = commonPattern({prop:{}});
ready
common pattern + magic set
globalResult = commonPattern(defineProperty({}, "prop", {
    get: function () {
        return this._prop;
    },
    set: function (_prop) {
        // here something more meaningful ...
        this._prop = _prop;
    }
}));
ready
common pattern + magic
globalResult = commonPattern(defineProperty({}, "prop", {
    get: function () {
        return this._prop || {}; // let's say the default
    },
    set: function (_prop) {
        // here something more meaningful ...
        this._prop = _prop;
    }
}));
ready
better pattern set
globalResult = betterPattern({});
ready
better pattern
globalResult = betterPattern({prop:{}});
ready
better pattern + magic set
globalResult = betterPattern(defineProperty({}, "prop", {
    get: function () {
        return this._prop;
    },
    set: function (_prop) {
        // here something more meaningful ...
        this._prop = _prop;
    }
}));
ready
better pattern + magic
globalResult = betterPattern(defineProperty({}, "prop", {
    get: function () {
        return this._prop || {}; // let's say the default
    },
    set: function (_prop) {
        // here something more meaningful ...
        this._prop = _prop;
    }
}));
ready

Revisions

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

  • Revision 1: published by WebReflection on
  • Revision 2: published by WebReflection on