0

So I've read up and down on the topic of combination inheritance in JavaScript. I get that the intent is to use prototype chaining for to inherit properties and methods-- and use constructor stealing to inherit instance properties.

I've provided an example that is boggling me and preventing me from fully understanding this concept.

In a nutshell, I create a SuperColors parent function that passes along its properties to SubColors by a call() execution in the SubColors constructor method. As I understand it, this should allow the instance (instance1) to have its own color properties as I've demonstrated.

Here's the quirky part. I delete the instance1's property of colors. This should mean that when I push new colors they should manipulate SuperColors color property to the full rainbow. Then when I create a new instance (instance2) of SubColors they should inherit the rainbow.

They don't though. If we look at the instance2 in console.log() the colors were instantiated with "Red,Orange,Yellow", even though we can clearly see that SuperColor's color property has the entire rainbow.

This doesn't make sense to me-- am I understanding prototype inheritance incorrectly or is this a weird quirk of the language that is unexpected?

function SuperColors() {
    this.colors = ["red", "orange", "yellow"];
}

SuperColors.prototype.sayColors = function () {
    alert("SuperColors " + this.colors);
};

function SubColors() {
    //inherit properties
    SuperColors.call(this);
}

// inherit methods
SubColors.prototype = new SuperColors();

SubColors.prototype.sayRainbow = function () {
    alert(this.colors + "a whole rainbow!");
};

// create an instance of SubColors
var instance1 = new SubColors();

// push colors to colors property on instance
instance1.colors.push("green", "blue", "purple");
alert(instance1.colors); // "red, orange, yellow, green, blue, purple"
instance1.sayColors(); // "SuperColors red,orange,yellow,green,blue,purple";

// delete instance of colors
delete(instance1.colors);
console.log(instance1);

// this should manipulate SuperColor's constructor of colors
instance1.colors.push("green", "blue", "purple");

// instantiate a new SubColor object that should inherit SuperColor's entire rainbow
var instance2 = new SubColors();

alert(instance1.colors);
alert(instance2.colors); // WHY ISN'T THIS THE ENTIRE RAINBOW? It should have been instantiated with SuperColor's modified colors.

console.log(instance2); // Shows that SuperColors.colors has the rainbow, but the instance has only 3 colors?

http://jsfiddle.net/ZKAZf/

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
AdamSchuld
  • 833
  • 9
  • 15

3 Answers3

2
// this should manipulate SuperColor's constructor of colors
delete instance1.colors;
instance1.colors.push("green", "blue", "purple");

Not exactly. It doesn't manipulate the SuperColor constructor, but the SubColor.prototype (a SuperColor instance), from which the instance1 inherits its .colors property (now that it has no own one any more).

// instantiate a new SubColor object that should inherit SuperColor's entire rainbow
var instance2 = new SubColors();

No, nothing changed in the inheritance process. instance2 still inherits from SubColor.prototype just as instance1 does. And the SuperColor constructor is still called on the new instance…

alert(instance2.colors); // WHY ISN'T THIS THE ENTIRE RAINBOW?

…where it creates a brand new array which is assigned to a new, own .colors property of the new instance! That new array is the one you're accessing, and it was never modified by anything.

If you would

delete instance2.colors;

then you could see the SubColor.prototype.colors as well when doing

alert(instance2.colors);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
1

Delete instance2.colors. Then you'll get the entire rainbow:

delete instance2.colors;
alert(instance2.colors);

See the demo: http://jsfiddle.net/ZKAZf/1/

You should read the following posts on inheritance in JavaScript:

  1. Aadit M Shah | Why Prototypal Inheritance Matters
  2. JavaScript inheritance and the constructor property
  3. Benefits of prototypal inheritance over classical?
  4. No ways to have class-based objects in javascript?
Community
  • 1
  • 1
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • But I shouldn't have to do that for every instance when making a new instance. The question is more about why every new instance doesn't instantiate with the rainbow spectrum when clearly SuperColors color property is "red,orange,yellow,green,blue,purple" – AdamSchuld Jul 16 '13 at 12:50
0

I think it's down to this:

function SubColors() {
    //inherit properties
    SuperColors.call(this);
}

What you are doing here is executing SuperColors but making this refer to the SubColors instance you're creating. Inside SuperColors the SubColors instance then gets given its own colors property - this hides the colors attribute on prototype.

So, when something tries to look up colors on your SubColours instance it finds something on that instance and doesn't look up the prototype chain any further. When you delete colors on instance1 subsequent lookups of instance1.colors now have to look up the prototype chain to find the SuperColors version, but when you create instance2, you are again creating colors on the SubColors instance which hides the version on SuperColors.

If you delete instance2.colors you will see that instance2.colors now resolves to the version of colors with teh whole rainbow.

Steve Allison
  • 1,091
  • 6
  • 6