原型继承中的奇怪行为

时间:2012-08-24 10:59:51

标签: javascript prototype

我对原型继承的概念比较新,所以也许这就是原型继承应该如何工作,或者这可能只是javascript但看起来像原型继承只是很好的主要类型。例如,我有以下代码:

var leg = {
    type: null
};

var Animal = {
  traits: {},
  leg: Object.create(leg)
};

var lion = Object.create(Animal);
lion.traits.legs = 4;
lion.leg.type = 'left';

var bird = Object.create(Animal);
bird.traits.legs = 2;
bird.leg.type = 'right';

alert(lion.traits.legs) // shows 2???
alert(lion.leg.type) // shows right???

最后两行显示我的困惑。这真的是原型继承应该如何工作,还是这就是javascript如何实现它?

如果这真的是原型继承应该如何工作,我真的不知道这种类型的继承在大多数情况下是如何有用的。如果我只能有原始类型,那么创建复杂对象似乎非常有限,因为在很多情况下我有一个对象存储另一个对象的实例。

2 个答案:

答案 0 :(得分:2)

不要继承非原始状态。继承方法。使每个对象都有自己的状态。状态是使对象唯一的原因,如果所有对象共享相同的状态,则没有意义。

var Animal = {
    method1: function() {},
    method2: function() {}
};

var lion = Object.create(Animal, {
    traits: {
        value: {}
    },
    leg: {
        value: {
            type: null
        }
    }
});

var bird = Object.create(Animal, {
    traits: {
        value: {}
    },
    leg: {
        value: {
            type: null
        }
    }
});

顺便说一句,对于做同样的事情,有一个更简洁,更好的支持语法:

function Animal(traits, leg) {
    this.traits = traits;
    this.leg = leg;
}

var method = Animal.prototype;

method.method1 = function() {

};

method.method2 = function() {

};


var lion = new Animal({}, {type: null}),
    bird = new Animal({}, {type: null});

答案 1 :(得分:0)

,这是应该如何运作的。属性traitsleg是可变对象,它们在实例之间共享。原型继承的想法是你从原型继承所有状态,除非你明确地覆盖它。您不会覆盖字段traitleg,因此它们会与原型共享。

这与基于类的继承不同,其中state永远不会被继承,您必须初始化构造函数中的所有状态。

可以拥有复杂的对象,但如果每个实例都需要拥有自己的对象字段的新实例,则必须在创建实例后创建它们,就像在构造函数中一样。

原型继承很有用(与基于类的继承相比),因为:

  1. 您可以节省大量内存,因为您只为与原型不同的字段分配“插槽”。在基于类的对象中,您总是必须为所有字段分配空间,即使它们永远不会从默认值更改。

  2. 继承更改很容易。例如。例如,如果您在UI框架中有一个“窗口”原型,并且从该原型继承了许多具体窗口,您可以更改原型上的颜色,并自动继承到未明确覆盖它的所有实例。 / p>