2

我对原型继承的概念相对较新,所以也许这就是原型继承应该如何工作,或者这只是 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 实现它的方式?

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

4

2 回答 2

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});
于 2012-08-24T11:04:06.437 回答
0

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

这与从不继承状态的基于类的继承不同,您必须在构造函数中初始化所有状态。

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

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

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

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

于 2012-08-24T11:04:48.760 回答