Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper Javascript inheritance

I am wondering whether it is possible to inherit constructor in javascript. In the following example, I'd like the Moveable to assign x and y arguments to this.x and this.y respectivelly, as I defined in Sprite. Also, what would be the best way (but still short and readable) to define the prototype without creating the instation of ancestor? It would be best to assign it in the class itself, not in the outside scope as I it is now:

function Sprite(x, y) {
    this.x = x ? x : 0;
    this.y = y ? y : 0;     
    this.getPos = function() {
        return {
            x: this.x,
            y: this.y
        };
    };
}

function Moveable(x, y) {

}
Moveable.prototype = new Sprite();
like image 210
Mikulas Dite Avatar asked Feb 13 '11 16:02

Mikulas Dite


People also ask

Which is correct regarding inheritance in JavaScript?

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.

Is inheritance possible in JavaScript?

In JavaScript, an object can inherit properties of another object. The object from where the properties are inherited is called the prototype. In short, objects can inherit properties from other objects — the prototypes.

What is the point of prototypal inheritance?

The Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the [[Prototype]] of an object, we use Object.


3 Answers

You'd call the parent constructor like this:

function Moveable(x, y) {
    Sprite.call(this, x, y);
}

I'm afraid there's no short way of setting up the inheritance if you want to use pseudo-classical inheritance, and no way of doing it inside the scope of the constructor function.

You can get around instantiating your base class though, if you construct a temporary empty object. Looks complicated but is commonly used as a helper function (like in the Google Closure Library goog.inherits method from where I more or less copied this):

var inherits = function(childConstructor, parentConstructor) {
  function tempConstructor() {};
  tempConstructor.prototype = parentConstructor.prototype;
  childConstructor.prototype = new tempConstructor();
  childConstructor.prototype.constructor = childConstructor;
};

inherits(Moveable, Sprite);

// instantiating Moveable will call the parent constructor
var m = new Moveable(1,1);
like image 21
meyertee Avatar answered Sep 29 '22 10:09

meyertee


Think of a function as two pieces: the constructor function and the prototype object. Take two of these function classes and mix them together. Mixing the objects are simple enough, the trick is to mix the constructors.

var Sprite = function(x, y, w, h){
   console.log("Sprite constr:", x, y, w, h);
}

var Moveable = function(x, y, w, h){
   console.log("Moveable constr:", x, y, w, h);
}

var extend = function(class1, class2){
   // here we make a new function that calls the two constructors. 
   // This is the "function mix" 
   var f = function(){
      class1.prototype.constructor.apply(this, arguments);
      class2.prototype.constructor.apply(this, arguments);
   }
   // now mix the prototypes
   f.prototype = library.objectmix(class1.prototype, class2.prototype);
   return f;
}

var MoveableSprite = extend(Sprite, Moveable);
like image 44
mwilcox Avatar answered Sep 29 '22 10:09

mwilcox


The standard way to call a superclass constructor is using Function.call:

function Moveable(x, y) {
  Sprite.call(this, x, y);
}

As for the prototype, you can do something like this to chain the prototype without creating an instance of the superclass:

function makePrototype(superclass) {
  function f() { }
  f.prototype = superclass.prototype;
  return new f();
}

Moveable.prototype = makePrototype(Sprite);

This uses a dummy constructor to create an object that shares the same prototype as Sprite, and since that's all JavaScript cares about, instances of Moveable are considered instanceof Sprite.

This isn't "short and readable" as you asked for, but the only other choice is to entirely skip prototypes and assign members directly within the constructor.

Edit: As @Raynos points out, you also want to set the constructor property (which is done by default by JavaScript but is lost as soon as you reset Moveable.prototype):

Moveable.prototype.constructor = Moveable;
like image 62
casablanca Avatar answered Sep 29 '22 09:09

casablanca