2

I've been spending my past couple hours researching prototypical inheritance, but I'm left with conflicting/unclear answers on how it should be done. It seems to be working for how I'm using it right now.

Paper.Component = function(){}; // useless unless I can solve problem mentioned below?
Paper.Component.prototype = {
 isInBounds: function(x, y){
 // ...
 },
 setPosition: function(x, y){
 // ...
 },
 setSize: function(w, h){
 // ...
 }
};
Paper.Button = function(x, y, w, h, text){
 // ...
}
Paper.Button.prototype = Object.create(Paper.Component.prototype);

It also seems to have another problem; How can I have Paper.Button save it's constructor information (x,y,w,h) onto Paper.Component rather than on itself? I.e., how can every child of Paper.Component inherit and set these values?

asked Oct 20, 2014 at 7:39
1

2 Answers 2

2

What you have so far is fine. The missing bit in Button looks like this:

Paper.Button = function(x, y, w, h, text){
 Paper.Component.call(this, /*...any args required by it...*/);
 // Button stuff here...
};

Function#call calls a function with a specific this value and any arguments you pass it. So the above calls Paper.Component from within Paper.Button with this referencing the current object, and passing along any appropriate arguments.

You also want to set the constructor property on any prototype you replace rather than just adding to. It's largely optional (JavaScript itself doesn't use constructor for anything), but since the JavaScript engine sets it on the default prototype objects, we should set it when replacing them, just so we're consistent with the default prototypes.

Slightly simpler, concrete example:

function Shape(sides, color) {
 this.sides = sides;
 this.color = color;
}
// Shape.prototype.method = ...
function Rectangle(color) {
 Shape.call(this, 4, color);
 // Rectangle stuff here...
}
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle; // <== The constructor bit
// Rectangle.prototype.method = ...

If you're interested in setting up hierarchies of "classes" of objects using prototypical inheritance in JavaScript, you might want to look at my Lineage helper script, which automates the above with a simpler syntax and provides other useful features.

answered Oct 20, 2014 at 7:41
Sign up to request clarification or add additional context in comments.

3 Comments

Very well explained, thank you. If I ever run into the need to provide exclusively functions to inherited objects, would the constructor just be an empty function as seen in my original post? Paper.Component = function(){}; I've tried Paper.Component = {};, but I cannot seem to add a prototype to that?
@John: If you like, yes, and if you're building hierarchies with constructor functions (as you are), that's probably best. Alternately, you don't actually need the Component function, you could just have an object you use to create the Button prototype (and then have Button not call it). But it's probably best to be consistent.
@John: "I've tried Paper.Component = {};, but I cannot seem to add a prototype to that?" You were adding that as I was commenting above. Yes, that's what I meant. At that point, Paper.Component would be the object you'd use with Object.create to create the Button prototype: Paper.Button.prototype = Object.create(Paper.Component); (and you'd put isInBounds and such directly on Paper.Component). But I would probably stick with the empty function, for consistency.
1

A good reference is the MDN - Inheritance revisited page

What you are looking for (I think) is something like this:

Paper.Component = function(x,y,w,h){
 this.setPosition( x, y );
 this.setSize( w, h );
}; 
Paper.Component.prototype.isInBounds = function(x, y){};
Paper.Component.prototype.setPosition = function(x, y){};
Paper.Component.prototype.setSize = function(w, h){};
Paper.Button = function(x, y, w, h, text){
 Paper.Component.apply( this, arguments );
}
Paper.Button.prototype = Object.create(Paper.Component.prototype);
Paper.Button.prototype.constructor = Paper.Button;

Things to note:

  • Do not do Paper.Component.prototype = { ... } as it will overwrite the current prototype (e.g. the existing .prototype.constructor and anything else anyone has already created).
  • Remember to set the constructor (the last line).
Vogel612
5,6535 gold badges54 silver badges79 bronze badges
answered Oct 20, 2014 at 7:52

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.