JavaScript’s Object.keys performance with inheritance chains

javascript
Published

October 23, 2013

Backstory: (You can cut to the chase) I’m working on a JavaScript library in which I want to identify any changes a method has made to properties of the object it is applied to, preferably in a more intelligent way than cloning all the properties and comparing them all before and after invocation. This can be done by applying the method in question to an empty object x inheriting from the true/intended object, and looking for any properties in x after the method is applied.

But, how does one efficiently look for the properties in x? In JS implementations supporting ECMAScript 5, Object.keys looks like a promising candidate. The function is decidedly O(n), but I wanted to be sure that with ES5, “n” is the properties of just my object, and not properties of all objects in the inheritance chain, like the ES3 polyfill.

(The chase:) My test on jsperf.com shows that yes, in browsers with ES5, Object.keys doesn’t waste time iterating properties of the inheritance chain and discarding them.

See also a simple html page with some primitive timings, which basically says the same thing:

<html>
<head>
<script>
function BaseClass() {}
for (var i = 0; i < 10e4; i++) {
  BaseClass.prototype["p" + i] = i;
}

function SubClass() {
this.thing = 'x';
}
SubClass.prototype = BaseClass.prototype;

var objInTest = new SubClass();


function polyfillKeys(obj) {
  var output = [];
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      output.push(key);
    }
  }
  return output;
}
// could do Object.keys = polyfillKeys

var start = new Date();
var keys = Object.keys(objInTest);
console.log("Native Object.keys: " + (new Date() - start));

start = new Date();
var keys = polyfillKeys(objInTest);
console.log("Polyfill way: " + (new Date() - start));
</script>
</head>
<body></body>
</html>