Javascript 原型遗传中的Wierd行为

Javascript 原型遗传中的Wierd行为,javascript,prototype,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

我对原型继承的概念比较陌生,所以可能这就是原型继承应该如何工作,或者这只是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实现的方式


如果这真的是原型继承应该如何工作的话,我真的不认为这种类型的继承在大多数情况下会有什么用处。如果我只能使用基元类型,那么在创建复杂对象时这似乎非常有限,因为在许多情况下,我的对象存储了另一个对象的实例。

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

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});

是的,这就是它的工作原理。属性
traits
leg
是实例之间共享的可变对象。原型继承的思想是,除非显式重写原型,否则从原型继承所有状态。您不重写字段
trait
leg
,因此它们与原型共享

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

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

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

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

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


  • 所有实例都共享
    traits
    leg
    对象。只向应该共享的原型添加属性,所有特定于实例的属性都属于构造函数。