Javascript组合继承 - 意外结果

时间:2013-07-16 11:50:16

标签: javascript

所以我上下阅读了JavaScript中的组合继承主题。我认为目的是使用原型链来继承属性和方法 - 并使用构造函数窃取来继承实例属性。

我提供了一个令我难以置信的例子,并阻止我完全理解这个概念。

简而言之,我创建了一个SuperColors父函数,它通过SubColors构造函数方法中的call()执行将其属性传递给SubColors。据我了解,这应该允许实例(instance1)拥有自己的颜色属性,如我所示。

这是古怪的部分。我删除了instance1的颜色属性。这应该意味着当我推动新颜色时,他们应该将SuperColors颜色属性操纵为完整的彩虹。然后当我创建一个SubColors的新实例(instance2)时,他们应该继承彩虹。

他们不是。如果我们在console.log()中查看instance2,颜色会被实例化为“红色,橙色,黄色”,即使我们也可以清楚地看到SuperColor的颜色属性具有整个彩虹。

这对我没有意义 - 我是不正确地理解原型继承还是这是一种奇怪的语言怪癖?

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/

3 个答案:

答案 0 :(得分:2)

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

不完全是。它不会操纵SuperColor构造函数,而是SubColor.prototype(一个SuperColor实例),instance1从中继承其.colors属性(现在它没有自己的了。)

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

不,继承过程中没有任何改变。 instance2仍然SubColor.prototype继承instance1。并且仍在新实例上调用SuperColor构造函数...

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

...它创建了一个全新的数组,该数组被分配给新实例的新的自己的 .colors属性!那个新数组是你正在访问的数组,它从未被任何东西修改过。

如果你愿意

delete instance2.colors;

然后你可以在做

时看到SubColor.prototype.colors
alert(instance2.colors);

答案 1 :(得分:1)

删除instance2.colors。然后你会得到整个彩虹:

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

请参阅演示:http://jsfiddle.net/ZKAZf/1/

您应该阅读以下有关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?

答案 2 :(得分:0)

我认为这取决于此:

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

您在此处执行的操作是SuperColors,但使this引用您正在创建的SubColors实例。在SuperColors内部,SubColors实例会获得自己的colors属性 - 会隐藏原型上的colors属性。

因此,当某些内容试图在colors实例上查找SubColours时,它会在该实例上找到,并且不会再查找原型链。当您在colors上删除instance1时,instance1.colors的后续查找现在必须查找原型链以查找SuperColors版本,但在创建instance2时,您将再次在colors实例上创建SubColors,该实例会隐藏SuperColors上的版本。

如果您delete instance2.colors,您会看到instance2.colors现已解析为colors的版本,而且整个彩虹。