0

I have been trying to learn the ins and outs of Javascript's inheritance structure and I came across this problem. I'm trying to create several subclass objects and assign values to them immediately by passing a variable upon their creation.

For instance, below the parent class GamePiece receives a random property as a variable upon its creation and sets it as myProperty which works fine of course when creating a new GamePiece object. However, if I wanted to set that variable on the creation of a Pawn object, it does not pass into its parent and remains unset. The obvious fix is to just define the variable again on the subclass but that, correct me if I'm wrong, seems to defeat the purpose of defining a parent class. You can also successfully set the variable by passing the parameter as Pawn.prototype = new GameObject("foo"); but that doesn't help when creating multiple Pawn() objects. Is there a common way of doing this that I am missing?

var GamePiece = function (randomProperty) {
  this.myProperty = randomProperty || "never set";
  this.print = function () {
    console.log(this.myProperty);
  }
}

var Pawn = function (randomProperty) {
  this.print = function () {
    console.log(this.myProperty);
  }
}

//Setting a value on creation
piece = new GamePiece("foo");
piece.print(); // Produces "foo" naturally

//Setting the prototype
Pawn.prototype = new GamePiece();

//Try to pass value through the creation of subclass
pawn = new Pawn("foo");
pawn.print(); // Produces "never set"
  • Creating an instance of Parent to be used as prototype of Parent shows a lack of understanding of the roles the constructor and prototype play. Maybe the following answer can help you: http://stackoverflow.com/a/16063711/1641941 – HMR Jan 16 '15 at 23:43

1 Answers1

0

You must call you parent class in context of current this, using call or apply method:

var GamePiece = function (randomProperty) {
    this.myProperty = randomProperty || "never set";
    this.print = function () {
        console.log(this.myProperty);
    }
}

var Pawn = function (randomProperty) {
    Game.call(this, randomProperty);
    // or Game.apply(this, [randomProperty]);
}

But much it's better to keep methods in prototype. So next code will be better:

var GamePiece = function (randomProperty) {
    this.myProperty = randomProperty || "never set";

    //... some another properties initialization
};

GamePiece.prototype.print = function () {
    console.log(this.myProperty);
};

var Pawn = function (randomProperty) {
    Game.call(this, randomProperty);
    // or Game.apply(this, [randomProperty]);

    //... some Pawn properties initialization
};

Pawn.prototype = Object.create(Game.prototype, { constructor: { value: Pawn }});

Pawn.prototype.someMethod = function() {
    // Some Pawn method logic
};

But ES6 is coming (will become recommendation in June 2015), so you can start preparation for using them. See here, here and here

alexpods
  • 47,475
  • 10
  • 100
  • 94
  • Is there a more general way without using the actual prototype name? Like this.prototype.call()? –  Jan 16 '15 at 20:42
  • @bryeetz What do you mean not using actual prototype name? Not using `Game` name? – alexpods Jan 16 '15 at 20:43
  • Yeah, as if you didn't know the name of the Parent, you just wanted to access the Parent object –  Jan 16 '15 at 20:44
  • @bryeetz You must specify parent class name at least once. For example es6 code: `class Pawn extends Game`. – alexpods Jan 16 '15 at 20:47
  • @bryeetz If you means call parent method in subclass method - then in ES5 it's not possible (You can just write something: `var parent = Game.prototype` and then using `parent` to call its methods). In ES6 `super` keyword exists for this purpose – alexpods Jan 16 '15 at 20:49
  • @bryeetz I've updated the answer, specified some ES6 classes links. – alexpods Jan 16 '15 at 20:54