2

I am struggling accessing a property that is set on a child object and accessing it via method on its prototype.

var Parent = function () {
    this.getColor = function () {
        return this.color;
    };
};

var Child = function () {
    this.color = red;
};

Child.prototype = new Parent;

var Test = new Child();

console.log(Test.getColor());
=> undefined

Any and all assistance is appreciated.

Muath
  • 4,351
  • 12
  • 42
  • 69
Jared Meyering
  • 1,291
  • 2
  • 11
  • 21
  • That works just fine -> **http://jsfiddle.net/eYnPq/**, as long as `red` is defined. – adeneo Jul 20 '14 at 17:48
  • 1
    @adeneo your version has quotes around `red` :) – Pointy Jul 20 '14 at 17:48
  • 2
    @Pointy - I assumed it was a variable, and it's probably `undefined`. If it wasn't declared it would be an error. – adeneo Jul 20 '14 at 17:49
  • 1
    Yes I think that's where the `undefined` in the OP version is coming from; the assignment leaves `this.color` as `undefined`. – Pointy Jul 20 '14 at 17:50
  • @Pointy - seems like the only possible way for that result, so the answer is that `red` *is* declared, but it has no value, hence `undefined` – adeneo Jul 20 '14 at 17:50
  • Adding the method to the this object during construction causes every instance to have its own copy of the method. Also, classes that inherit from Parent will not inherit the method (any object can be ASSIGNED a copy of the method if you call the Parent constructor however) . You should instead add methods as properties of the Parent.prototype object so that instances share one copy of the method and the method is inheritable. – orb Jul 20 '14 at 18:28
  • Maybe the following answer can help you understand more: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Jul 21 '14 at 01:37

1 Answers1

3

Here's how I'd do it

function Parent(color) {

  function getColor() {
    return color;
  }

  // export public functions
  this.getColor = getColor;
}

Now for the Child

function Child(color) {
  Parent.call(this, color);
}

Child.prototype = Object.create(Parent.prototype, {
  constructor: {value: Child}
});

Let's see it work

var c = new Child("red");
c.getColor(); // "red";

Explanation:

The important bits of the Child constructor

  1. Make sure to call the Parent constructor with the context of the Child instance (this)

    Parent.call(this, color);
    
  2. Setup the Child.prototype based off of the Parent.prototype

    Child.prototype = Object.create(Parent.prototype, {
      constructor: {value: Child}
    });
    

    You can see the node.js implementation of util.inherits uses a similar method.

    This somewhat complicated line does two things for you. 1) It avoids invoking the parent constructor unnecessarily, 2) It sets the constructor property properly.

    var c = new Child("red");
    c instanceof Child;  // true
    c instanceof Parent; // true
    c.constructor.name;  // "Child"
    

    But using your code, you would see

    var c = new Child("red");
    c instanceof Child;  // true
    c instanceof Parent; // true
    c.constructor.name;  // "Parent"
    

    This may or may not be a concern for you, but depending on how you want to use your parent/child objects, it may be hard to programmatically differentiate which objects are from the Parent constructor and which ones are from the Child constructor.


Ok, let's see another way to do it by assigning the color property on the object itself

function Parent(color) {
  this.color = color;
}

We'll add the getColor method directly to the Parent.prototype

Parent.prototype.getColor = function getColor() {
  return this.color;
};

The Child constructor will stay the same. Keep in mind we'll use the same inheritance pattern we used above

function Child(color) {
  Parent.call(this, color);
}

Child.prototype = Object.create(Parent.prototype, {
  constructor: {value: Child}
});

Lastly, let's get the color using our getColor method

var c = new Child("red");
c.getColor(); // "red"

Or you could access the property on the object directly

c.color; // "red"
maček
  • 76,434
  • 37
  • 167
  • 198
  • No. The primary reason for this somewhat complicated line is to use `Object.create` for inheriting from the `Parent`'s prototype without invoking the constructor. The second parameter to `Object.create` could be omitted and replaced by a simple property assignment. – Bergi Jul 20 '14 at 19:05
  • @Bergi, "primary reasons" aside, it objectively does two things, and thank you for calling out one I didn't mention. I've edited my post to leave my opinions out of the matter :) – maček Jul 20 '14 at 19:18
  • 1
    You know that you didn't really answer the question, right? It doesn't matter if there is a better way of setting up inheritance - if the OP doesn't have a grasp of *what* the code he/she currently has is doing and *why* it's not working, just throwing other patterns at him/her is not really going to help. – Stephen Jul 20 '14 at 19:18
  • I must admit that Stephen is right (though that "triviality" has been settled in the comments already), but have a +1 for the correct inheritance nonetheless :-) – Bergi Jul 20 '14 at 19:20
  • Fair enough, gentlemen. I've added an alternative solution that shows how to set the value as a property on the object itself. Thanks for the constructive feedback. – maček Jul 20 '14 at 19:29