I'm looking for a simple way of creating two classes, one inheriting from the other, and the child redefining one of the parent's methods, and inside the new method, calling the parent's.
For example, having a class Animal
and Dog
, where the Animal class defines a method makeSound()
which establishes how to output a sound, which Dog then overrides in its own makeSound()
method to make a "woof" sound, but while also calling Animal's makeSound()
to output that woof.
I looked at John Resig's model here, but it uses the native arguments.callee
property which is apparently depreciated in ECMA script 5. Does that mean I shouldn't use John Resig's code?
What would one neat, simple way of writing my animal/dog code using Javascript's prototype inheritance model?
JavaScript does not support multiple inheritance, but mixins can be implemented by copying methods into prototype. We can use mixins as a way to augment a class by adding multiple behaviors, like event-handling as we have seen above.
In JavaScript, inheritance is supported by using prototype object.
When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype.
Does that mean I shouldn't use John Resig's code?
Correct, not when you are using ES5 in strict mode. However, it can be easily adapted:
/* Simple JavaScript Inheritance for ES 5.1 * based on http://ejohn.org/blog/simple-javascript-inheritance/ * (inspired by base2 and Prototype) * MIT Licensed. */ (function(global) { "use strict"; var fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; // The base Class implementation (does nothing) function BaseClass(){} // Create a new Class that inherits from this class BaseClass.extend = function(props) { var _super = this.prototype; // Set up the prototype to inherit from the base class // (but without running the init constructor) var proto = Object.create(_super); // Copy the properties over onto the new prototype for (var name in props) { // Check if we're overwriting an existing function proto[name] = typeof props[name] === "function" && typeof _super[name] == "function" && fnTest.test(props[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, props[name]) : props[name]; } // The new constructor var newClass = typeof proto.init === "function" ? proto.hasOwnProperty("init") ? proto.init // All construction is actually done in the init method : function SubClass(){ _super.init.apply(this, arguments); } : function EmptyClass(){}; // Populate our constructed prototype object newClass.prototype = proto; // Enforce the constructor to be what we expect proto.constructor = newClass; // And make this class extendable newClass.extend = BaseClass.extend; return newClass; }; // export global.Class = BaseClass; })(this);
Prototype chain with Object.create() + assign constructor
function Shape () { this.x = 0; this.y = 0; } Shape.prototype.move = function (x, y) { this.x += x; this.y += y; }; function Rectangle () { Shape.apply(this, arguments); // super constructor w/ Rectangle configs if any } Rectangle.prototype = Object.create(Shape.prototype); // inherit Shape functionality // works like Rectangle.prototype = new Shape() but WITHOUT invoking the constructor Rectangle.prototype.constructor = Rectangle; var rect = new Rectangle(); rect instanceof Rectangle && rect instanceof Shape // returns true
from Object.create documentation
information about the new keyword
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With