goog.inherit Vs. simple inherit

JavaScript performance comparison

Revision 6 of this test case created by Benny Bennet

Preparation code


      
      <script>
Benchmark.prototype.setup = function() {
  var goog = {};
  goog.inherits = function(childCtor, parentCtor) { /** @constructor */
  
    function tempCtor() {};
    tempCtor.prototype = parentCtor.prototype;
    childCtor.superClass_ = parentCtor.prototype;
    childCtor.prototype = new tempCtor(); /** @override */
    childCtor.prototype.constructor = childCtor;
  };
  goog.base = function(me, opt_methodName, var_args) {
    var caller = arguments.callee.caller;
    if (caller.superClass_) {
      // This is a constructor. Call the superclass constructor.
      return caller.superClass_.constructor.apply(
      me, Array.prototype.slice.call(arguments, 1));
    }
  
    var args = Array.prototype.slice.call(arguments, 2);
    var foundCaller = false;
    for (var ctor = me.constructor;
    ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
      if (ctor.prototype[opt_methodName] === caller) {
        foundCaller = true;
      } else if (foundCaller) {
        return ctor.prototype[opt_methodName].apply(me, args);
      }
    }
  
    // If we did not find the caller in the prototype chain,
    // then one of two things happened:
    // 1) The caller is an instance method.
    // 2) This method was not called by the right caller.
    if (me[opt_methodName] === caller) {
      return me.constructor.prototype[opt_methodName].apply(me, args);
    } else {
      throw Error('goog.base called from a method of one name ' + 'to a method of a different name');
    }
  };
  
  var fnTest = /xyz/.test(function() {
    xyz;
  }) ? /\b_super\b/ : /.*/;
  
  Class = function() {};
  Class.extend = function extend(prop) {
    var _super = this.prototype;
  
    function Child() {
      if (this.init) this.init.apply(this, arguments);
    }
    Child.prototype = Object.create(this.prototype);
    Child.prototype.constructor = Child;
    Child.extend = extend;
  
    for (var name in prop) {
      // Check if we're overwriting an existing function
      if (typeof prop[name] == "function" && typeof _super[name] == "function" && /\b_super\b/.test(prop[name])) {
        Child.prototype[name] = (function(name, fn) {
          return function() {
            var tmp = this._super;
  
            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];
  
            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);
            this._super = tmp;
  
            return ret;
          };
        })(name, prop[name]);
      } else {
        Child.prototype[name] = prop[name];
      }
    }
    return Child;
  }
  
  
  ClassJR = function() {};
  
  // Create a new Class that inherits from this class
  ClassJR.extend = function(prop) {
    var _super = this.prototype;
  
    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;
  
    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ? (function(name, fn) {
        return function() {
          var tmp = this._super;
  
          // Add a new ._super() method that is the same method
          // but on the super-class
          this._super = _super[name];
  
          // The method only need to be bound temporarily, so we
          // remove it when we're done executing
          var ret = fn.apply(this, arguments);
          this._super = tmp;
  
          return ret;
        };
      })(name, prop[name]) : prop[name];
    }
  
    // The dummy class constructor
  
    function Class() {
      // All construction is actually done in the init method
      if (!initializing && this.init) this.init.apply(this, arguments);
    }
  
    // Populate our constructed prototype object
    Class.prototype = prototype;
  
    // Enforce the constructor to be what we expect
    Class.prototype.constructor = Class;
  
    // And make this class extendable
    Class.extend = arguments.callee;
  
    return Class;
  };
  
  ClassSG = function() {};
  
  
  
  // Create a new Class that inherits from this class
  ClassSG.extend = function(prop) {
  
    var _super = this.prototype;
  
  
  
    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    var Surrogate = function() {
        this.constructor = {};
        };
  
    Surrogate.prototype = this.prototype;
  
    prototype = new Surrogate;
  
  
  
    // Copy the properties over onto the new prototype
    for (var name in prop) {
  
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
  
      typeof _super[name] == "function" && fnTest.test(prop[name]) ?
  
      (function(name, fn) {
  
        return function() {
  
          var tmp = this._super;
  
  
  
          // Add a new ._super() method that is the same method
          // but on the super-class
          this._super = _super[name];
  
  
  
          // The method only need to be bound temporarily, so we
          // remove it when we're done executing
          var ret = fn.apply(this, arguments);
  
          this._super = tmp;
  
  
  
          return ret;
  
        };
  
      })(name, prop[name]) :
  
      prop[name];
  
    }
  
  
  
    // The dummy class constructor
  
    function Class() {
  
      // All construction is actually done in the init method
      if (this.init)
  
      this.init.apply(this, arguments);
  
    }
  
  
  
    // Populate our constructed prototype object
    Class.prototype = prototype;
  
  
  
    // Enforce the constructor to be what we expect
    Class.prototype.constructor = Class;
  
  
  
    // And make this class extendable
    Class.extend = arguments.callee;
  
  
  
    return Class;
  
  };
  
  BBClass = function(ctor) {
    ctor.prototype = {};
    ctor.prototype.constructor = ctor;
    ctor.extend = function(parent) {
      function ChildBB() {
        parent.prototype.constructor.apply(this, arguments);
        ctor.apply(this, arguments);
      };
      ChildBB.prototype = (typeof Object.create !== 'function') ? (function(parent) {
        function F() {};
        F.prototype = parent.prototype;
        var prototype = new F();
        prototype.constructor = ChildBB;
        return prototype;
      })(parent) : Object.create(parent.prototype, {
        constructor: {
          value: ChildBB,
          enumerable: false
        }
      });
      return ChildBB;
    }
    return ctor;
  };
  
  var googA = function() {
      this.a = 'a';
      this.b = 'b';
      this.c = this.a + this.b;
      };
  googA.prototype.foo = function() {
    return "foo"
  };
  googA.prototype.hello = function() {
    return "hello";
  };
  googA.prototype.foobar = function() {
    return "foobar";
  };
  googA.prototype.foobar2 = function() {
    return "foobar2";
  };
  
  var googB = function() {
      googA.call(this);
      };
  goog.inherits(googB, googA);
  googB.prototype.foo = function() {
    return googA.prototype.foo.call(this);
  };
  googB.prototype.bar = function() {
    return "bar";
  };
  googB.prototype.foobar = function() {
    return googB.superClass_.foobar.call(this);
  };
  googB.prototype.foobar2 = function() {
    return googA.prototype.foobar2.call(this);
  };
  
  var extendA = Class.extend({
    init: function() {
      //this is constructor
      this.a = 'a';
      this.b = 'b';
      this.c = this.a + this.b;
    },
    foo: function() {
      return "foo";
    },
    hello: function() {
      return "hello";
    },
    foobar: function() {
      return "foobar";
    }
  });
  
  var extendB = extendA.extend({
    init: function() {
      this._super();
    },
    foo: function() {
      this._super();
    },
    bar: function() {
      return "bar";
    },
    foobar: function() {
      return extendA.prototype.foobar.call(this)
    }
  });
  
  var extendJRA = ClassJR.extend({
    init: function() {
      //this is constructor
      this.a = 'a';
      this.b = 'b';
      this.c = this.a + this.b;
    },
    foo: function() {
      return "foo";
    },
    hello: function() {
      return "hello";
    },
    foobar: function() {
      return "foobar";
    }
  });
  
  var extendJRB = extendJRA.extend({
    init: function() {
      this._super();
    },
    foo: function() {
      this._super();
    },
    bar: function() {
      return "bar";
    },
    foobar: function() {
      return extendJRA.prototype.foobar.call(this)
    }
  });
  
  var extendSGA = ClassSG.extend({
    init: function() {
      //this is constructor
      this.a = 'a';
      this.b = 'b';
      this.c = this.a + this.b;
    },
    foo: function() {
      return "foo";
    },
    hello: function() {
      return "hello";
    },
    foobar: function() {
      return "foobar";
    }
  });
  
  var extendSGB = extendSGA.extend({
    init: function() {
      this._super();
    },
    foo: function() {
      this._super();
    },
    bar: function() {
      return "bar";
    },
    foobar: function() {
      return extendSGA.prototype.foobar.call(this)
    }
  });
  
  var bbClassA = BBClass(function() {
    //this is constructor
    this.a = 'a';
    this.b = 'b';
    this.c = this.a + this.b;
  });
  bbClassA.prototype = {
    foo: function() {
      return "foo";
    },
    hello: function() {
      return "hello";
    },
    foobar: function() {
      return "foobar";
    }
  };
  
  var bbClassB = BBClass(function() {}).extend(bbClassA);
  bbClassB.prototype.bar = function() {
    return "bar";
  };
  bbClassB.prototype.foobar = function() {
    return bbClassA.prototype.foobar.call(this);
  };
  
  function objA() {
    //this is constructor
    this.a = 'a';
    this.b = 'b';
    this.c = this.a + this.b;
  };
  objA.prototype = {
    foo: function() {
      return "foo";
    },
    hello: function() {
      return "hello";
    },
    foobar: function() {
      return "foobar";
    }
  };
  
  
  function objB() {};
  objB.prototype = Object.create(objA.prototype);
  objB.prototype.bar = function() {
    return "bar";
  };
  objB.prototype.foobar = function() {
    return objA.prototype.foobar.call(this);
  };
  
  fpAprototype = {
    foo: function() {
      return "foo";
    },
    hello: function() {
      return "hello";
    },
    foobar: function() {
      return "foobar";
    }
  };
  
  function createFPA() {
    var instance = Object.create(fpAprototype);
    //this is constructor
    instance.a = 'a';
    instance.b = 'b';
    instance.c = this.a + this.b;
    return instance;
  }
  
  var fpBprototype = Object.create(fpAprototype);
  fpBprototype.bar = function() {
    return "bar";
  };
  fpBprototype.foobar = function() {
    return fpAprototype.prototype.foobar.call(this);
  };
  
  function createFPB() {
    return Object.create(fpBprototype);
  
  }

};
</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
1.1 goog.inherit define classes
var googA = function() {
    this.a = 'a';
    this.b = 'b';
    this.c = this.a + this.b;
    };
googA.prototype.foo = function() {
  return "foo"
};
googA.prototype.hello = function() {
  return "hello";
};
googA.prototype.foobar = function() {
  return "foobar";
};
googA.prototype.foobar2 = function() {
  return "foobar2";
};

var googB = function() {
    googA.call(this);
    };
goog.inherits(googB, googA);
googB.prototype.foo = function() {
  return googA.prototype.foo.call(this);
};
googB.prototype.bar = function() {
  return "bar";
};
googB.prototype.foobar = function() {
  return googB.superClass_.foobar.call(this);
};
googB.prototype.foobar2 = function() {
  return googA.prototype.foobar2.call(this);
};
pending…
1.2 Extend define classes
var extendA = Class.extend({
  init: function() {
    //this is constructor
    this.a = 'a';
    this.b = 'b';
    this.c = this.a + this.b;
  },
  foo: function() {
    return "foo";
  },
  hello: function() {
    return "hello";
  },
  foobar: function() {
    return "foobar";
  }
});

var extendB = extendA.extend({
  init: function() {
    this._super();
  },
  foo: function() {
    this._super();
  },
  bar: function() {
    return "bar";
  },
  foobar: function() {
    return extendA.prototype.foobar.call(this)
  }
});
pending…
1.3 John Resig Extend define classes
var extendJRA = ClassJR.extend({
  init: function() {
    //this is constructor
    this.a = 'a';
    this.b = 'b';
    this.c = this.a + this.b;
  },
  foo: function() {
    return "foo";
  },
  hello: function() {
    return "hello";
  },
  foobar: function() {
    return "foobar";
  }
});

var extendJRB = extendJRA.extend({
  init: function() {
    this._super();
  },
  foo: function() {
    this._super();
  },
  bar: function() {
    return "bar";
  },
  foobar: function() {
    return extendJRA.prototype.foobar.call(this)
  }
});
pending…
1.4 Surrogate Extend define
var extendSGA = ClassSG.extend({
  init: function() {
    //this is constructor
    this.a = 'a';
    this.b = 'b';
    this.c = this.a + this.b;
  },
  foo: function() {
    return "foo";
  },
  hello: function() {
    return "hello";
  },
  foobar: function() {
    return "foobar";
  }
});

var extendSGB = extendSGA.extend({
  init: function() {
    this._super();
  },
  foo: function() {
    this._super();
  },
  bar: function() {
    return "bar";
  },
  foobar: function() {
    return extendSGA.prototype.foobar.call(this)
  }
});
pending…
2.1 Goog inherit object creation
var GA = new googA();
var GB = new googB();
pending…
2.2 Extend object creation
var EA = new extendA();
var EB = new extendB();
pending…
2.3 JR Extend object creation
var EJRA = new extendJRA();
var EJRB = new extendJRB();
pending…
2.4 Surrogate object creation
var ESGA = new extendSGA();
var ESGB = new extendSGB();
pending…
1.5 bennybennet define class
bbClassAprototype = {
  foo: function() {
    return "foo";
  },
  hello: function() {
    return "hello";
  },
  foobar: function() {
    return "foobar";
  }
};
var bbClassA = BBClass(function() {
  //this is constructor
  this.a = 'a';
  this.b = 'b';
  this.c = this.a + this.b;
}, bbClassAprototype);

var bbClassB = BBClass(function() {}).extend(bbClassA);
bbClassB.prototype.bar = function() {
  return "bar";
};
bbClassB.prototype.foobar = function() {
  return bbClassA.prototype.foobar.call(this);
};
pending…
1.5.2 bennybennet define class (cached functions)
function foo() {
  return "foo";
};

function hello() {
  return "hello";
};

function foobar() {
  return "foobar";
};
bbClassAprototype = {
  foo: foo,
  hello: hello,
  foobar: foobar
};
var bbClassA = BBClass(function() {
  //this is constructor
  this.a = 'a';
  this.b = 'b';
  this.c = this.a + this.b;
}, bbClassAprototype);

var bbClassB = BBClass(function() {}).extend(bbClassA);
bbClassB.prototype.bar = function() {
  return "bar";
};
bbClassB.prototype.foobar = function() {
  return bbClassA.prototype.foobar.call(this);
};
pending…
2.5 bennybennet object creation
var BBA = new bbClassA();
var BBB = new bbClassB();
pending…
1.6 Prototypal object define
function objA() {
  //this is constructor
  this.a = 'a';
  this.b = 'b';
  this.c = this.a + this.b;
};
objA.prototype = {
  foo: function() {
    return "foo";
  },
  hello: function() {
    return "hello";
  },
  foobar: function() {
    return "foobar";
  }
};

function objB() {};
objB.prototype = Object.create(objA.prototype);
objB.prototype.bar = function() {
  return "bar";
};
objB.prototype.foobar = function() {
  return objA.prototype.foobar.call(this);
};
pending…
2.6 Prototypal object creation
var obja = new objA();
var objb = new objB();
pending…
1.7 Factory Pattern object define
fpAprototype = {
  foo: function() {
    return "foo";
  },
  hello: function() {
    return "hello";
  },
  foobar: function() {
    return "foobar";
  }
};

function createFPA() {
  var instance = Object.create(fpAprototype);
  //this is constructor
  instance.a = 'a';
  instance.b = 'b';
  instance.c = this.a + this.b;
  return instance;
}

var fpBprototype = Object.create(fpAprototype);
fpBprototype.bar = function() {
  return "bar";
};
fpBprototype.foobar = function() {
  return fpAprototype.prototype.foobar.call(this);
};

function createFPB() {
  return Object.create(fpBprototype);

}
pending…
2.7 Factory Pattern object creation
var fpa1 = createFPA();
var fpb1 = createFPB();
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