0

因此,我已经阅读了有关 JavaScript 中组合继承的主题。我知道目的是使用原型链来继承属性和方法——并使用构造函数窃取来继承实例属性。

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

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

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

他们没有。如果我们查看 console.log() 中的 instance2,颜色被实例化为“Red,Orange,Yellow”,尽管我们可以清楚地看到 SuperColor 的 color 属性具有整个彩虹。

这对我来说没有意义——我是否错误地理解了原型继承,或者这是出乎意料的语言的奇怪怪癖?

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/

4

3 回答 3

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.prototypeinstance1。并且SuperColor构造函数仍然在新实例上调用......</p>

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

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

如果你愿意

delete instance2.colors;

那么你SubColor.prototype.colors在做的时候也可以看到

alert(instance2.colors);
于 2013-07-16T12:16:23.687 回答
1

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

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

查看演示:http: //jsfiddle.net/ZKAZf/1/

您应该阅读以下有关 JavaScript 继承的文章:

  1. 阿迪特 M 沙阿 | 为什么原型继承很重要
  2. JavaScript 继承和构造函数属性
  3. 原型继承优于经典继承的好处?
  4. 没有办法在 javascript 中拥有基于类的对象?
于 2013-07-16T12:20:09.913 回答
0

我认为这归结为:

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

您在这里所做的是执行SuperColors,但要this引用SubColors您正在创建的实例。SuperColors然后在实例内部SubColors获得它自己的colors属性 -这隐藏了colors原型上的属性

因此,当某些东西试图colors在您的SubColours实例上查找时,它会在该实例上找到某些东西,并且不会进一步查找原型链。当您colorsinstance1随后的查找中删除时,instance1.colors现在必须查找原型链以找到SuperColors版本,但是当您创建时instance2,您再次在隐藏版本colors的实例上创建。 SubColorsSuperColors

如果你delete instance2.colors会看到instance2.colors现在解决了colors整个彩虹的版本。

于 2013-07-16T12:16:21.800 回答