Prototypal inheritance vs Functional inheritance (v11)

Revision 11 of this benchmark created by Martín Acosta on


Description

This test suite compares performances of pure “prototypal inheritance” and “functional inheritance”. Both patterns have been well explained by Douglas Crockford in his book: JavaScript, The Good Parts.

The benchmark will create several objects built either with prototypal inheritance or functional inheritance, with an inheritance chain of 10 levels, and then will call methods on them.

Setup

var extend = function (myObject, newObj) {
      Object.keys(newObj).forEach(function (item) {
          myObject[item] = newObj[item];
      });
    };
    
    // Functional inheritance
    var object1 = function () {
      var publicMethods = {
        prop1: 'prop1',
        method1: function () {
          return this.prop1;
        }
      };
    
      return function () {
        var that = {};
        extend(that, publicMethods);
        return that;
      };
    }();
    
    var object2 = function () {
      var publicMethods = {
        prop2: 'prop2',
        method2: function () {
          return this.prop2;
        }
      };
    
      return function () {
        var that = object1();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    var object3 = function () {
      var publicMethods = {
        prop3: 'prop3',
        method3: function () {
          return this.prop3;
        }
      };
    
      return function () {
        var that = object2();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    var object4 = function () {
      var publicMethods = {
        prop4: 'prop4',
        method4: function () {
          return this.prop4;
        }
      };
    
      return function () {
        var that = object3();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    var object5 = function () {
      var publicMethods = {
        prop5: 'prop5',
        method5: function () {
          return this.prop5;
        }
      };
    
      return function () {
        var that = object4();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    var object6 = function () {
      var publicMethods = {
        prop6: 'prop6',
        method6: function () {
          return this.prop6;
        }
      };
    
      return function () {
        var that = object5();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    var object7 = function () {
      var publicMethods = {
        prop7: 'prop7',
        method7: function () {
          return this.prop7;
        }
      };
    
      return function () {
        var that = object6();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    
    var object8 = function () {
      var publicMethods = {
        prop8: 'prop',
        method8: function () {
          return this.prop8;
        }
      };
    
      return function () {
        var that = object7();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    var object9 = function () {
      var publicMethods = {
        prop9: 'prop',
        method9: function () {
          return this.prop9;
        }
      };
    
      return function () {
        var that = object8();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    
    var object10 = function () {
      var publicMethods = {
        prop10: 'prop',
        method10: function () {
          return this.prop10;
        }
      };
    
      return function () {
        var that = object9();
        extend(that, publicMethods);
        return that;
      };
    }();
    
    // Prototypal inheritance
    var inherits = function(Child, Parent) {
      function F() { }
      F.prototype = Parent.prototype;
      Child.prototype = new F;
    };
    
    var Object1 = function () {};
    Object1.prototype.prop1 = 'prop1';
    Object1.prototype.method1 = function () {
      return this.prop1;
    };
    
    var Object2 = function () {
      Object1.call(this);
    };
    inherits(Object2, Object1);
    Object2.prototype.prop2 = 'prop2';
    Object2.prototype.method2 = function () {
      return this.prop2;
    };
    
    var Object3 = function () {
      Object2.call(this);
    };
    inherits(Object3, Object2);
    Object3.prototype.prop3 = 'prop3';
    Object3.prototype.method3 = function () {
      return this.prop3;
    };
    
    var Object4 = function () {
      Object3.call(this);
    };
    inherits(Object4, Object3);
    Object4.prototype.prop4 = 'prop4';
    Object4.prototype.method4 = function () {
      return this.prop4;
    };
    
    var Object5 = function () {
      Object4.call(this);
    };
    inherits(Object5, Object4);
    Object5.prototype.prop5 = 'prop5';
    Object5.prototype.method5 = function () {
      return this.prop5;
    }
    
    var Object6 = function () {
      Object5.call(this);
    };
    inherits(Object6, Object5);
    Object6.prototype.prop6 = 'prop6';
    Object6.prototype.method6 = function () {
      return this.prop6;
    };
    
    var Object7 = function () {
      Object6.call(this);
    };
    inherits(Object7, Object6);
    Object7.prototype.prop7 = 'prop7';
    Object7.prototype.method7 = function () {
      return this.prop7;
    };
    
    var Object8 = function () {
      Object7.call(this);
    };
    inherits(Object8, Object7);
    Object8.prototype.prop8 = 'prop8';
    Object8.prototype.method8 = function () {
      return this.prop8;
    };
    
    var Object9 = function () {
      Object8.call(this);
    };
    inherits(Object9, Object8);
    Object9.prototype.prop9 = 'prop9';
    Object9.prototype.method9 = function () {
      return this.prop9;
    };
    
    var Object10 = function () {
      Object9.call(this);
    };
    inherits(Object10, Object9);
    Object10.prototype.prop10 = 'prop10';
    Object10.prototype.method10 = function () {
      return this.prop10;
    };
    
    // Prototypal inheritance where all functions are bound to this
    var BObject1 = function () {
      this.method1 = this.method1.bind(this);
    };
    BObject1.prototype.prop1 = 'prop1';
    BObject1.prototype.method1 = function () {
      return this.prop1;
    };
    
    var BObject2 = function () {
      BObject1.call(this);
      this.method2 = this.method2.bind(this);
    };
    inherits(BObject2, BObject1);
    BObject2.prototype.prop2 = 'prop2';
    BObject2.prototype.method2 = function () {
      return this.prop2;
    };
    
    var BObject3 = function () {
      BObject2.call(this);
      this.method3 = this.method3.bind(this);
    };
    inherits(BObject3, BObject2);
    BObject3.prototype.prop3 = 'prop3';
    BObject3.prototype.method3 = function () {
      return this.prop3;
    };
    
    var BObject4 = function () {
      BObject3.call(this);
      this.method4 = this.method4.bind(this);
    };
    inherits(BObject4, BObject3);
    BObject4.prototype.prop4 = 'prop4';
    BObject4.prototype.method4 = function () {
      return this.prop4;
    };
    
    var BObject5 = function () {
      BObject4.call(this);
      this.method5 = this.method5.bind(this);
    };
    inherits(BObject5, BObject4);
    BObject5.prototype.prop5 = 'prop5';
    BObject5.prototype.method5 = function () {
      return this.prop5;
    }
    
    var BObject6 = function () {
      BObject5.call(this);
      this.method6 = this.method6.bind(this);
    };
    inherits(BObject6, BObject5);
    BObject6.prototype.prop6 = 'prop6';
    BObject6.prototype.method6 = function () {
      return this.prop6;
    };
    
    var BObject7 = function () {
      BObject6.call(this);
      this.method7 = this.method7.bind(this);
    };
    inherits(BObject7, BObject6);
    BObject7.prototype.prop7 = 'prop7';
    BObject7.prototype.method7 = function () {
      return this.prop7;
    };
    
    var BObject8 = function () {
      BObject7.call(this);
      this.method8 = this.method8.bind(this);
    };
    inherits(BObject8, BObject7);
    BObject8.prototype.prop8 = 'prop8';
    BObject8.prototype.method8 = function () {
      return this.prop8;
    };
    
    var BObject9 = function () {
      BObject8.call(this);
      this.method9 = this.method9.bind(this);
    };
    inherits(BObject9, BObject8);
    BObject9.prototype.prop9 = 'prop9';
    BObject9.prototype.method9 = function () {
      return this.prop9;
    };
    
    var BObject10 = function () {
      BObject9.call(this);
      this.method10 = this.method10.bind(this);
    };
    inherits(BObject10, BObject9);
    BObject10.prototype.prop10 = 'prop10';
    BObject10.prototype.method10 = function () {
      return this.prop10;
    };
    
    var ob10 = object10();
    
    var Ob10 = new Object10();
    
    var BOb10 = new BObject10();

Test runner

Ready to run.

Testing in
TestOps/sec
object10()
object10();
ready
new Object10()
new Object10;
ready
obj10.methods()
ob10.method1();
ob10.method2();
ob10.method3();
ob10.method4();
ob10.method5();
ob10.method6();
ob10.method7();
ob10.method8();
ob10.method9();
ob10.method10();
ready
Ob10.methods()
Ob10.method1();
Ob10.method2();
Ob10.method3();
Ob10.method4();
Ob10.method5();
Ob10.method6();
Ob10.method7();
Ob10.method8();
Ob10.method9();
Ob10.method10();
ready
new BObject10()
new BObject10();
ready
BOb10.methods()
BOb10.method1();
BOb10.method2();
BOb10.method3();
BOb10.method4();
BOb10.method5();
BOb10.method6();
BOb10.method7();
BOb10.method8();
BOb10.method9();
BOb10.method10();
ready

Revisions

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