JavaScript 原型继承

JavaScript prototype inheritance

下面是一个简单的 JavaScript 继承示例。我们可以替换行:Dog.prototype = new Animal();
Dog.prototype = Animal.prototype?

我已经在浏览器中测试过,他们给我的结果是一样的。我很奇怪为什么我们需要创建一个新的 Animal 对象并将其分配给 Dog.prototype。

function Animal(age){
    this.age = age;
}

Animal.prototype.walk = function(){
     console.log("Walk"); 
}

function Dog(color, age){
    this.color = color;
    Animal.call(this, age)
}

Dog.prototype = new Animal();      //Why not Dog.prototype = Animal.prototype
Dog.prototype.constructor = Dog;


dog_b = new Dog("yellow", 9);
console.log("Age: " + dog_b.age +  " Color: " + dog_b.color );
dog_b.walk()

在这种特殊情况下,您可以出于一个简单的原因替换这些行:

function Dog(color, age) {
    this.color = color;
    Animal.call(this, age); // This line
}

在这里,您使用 call 提供的 this 调用 Animal 的构造函数,从而手动建立 Animal 的上下文。因此 function Animal 中的 this 将始终引用 Dog 的对象。这就是为什么 new 根本不会产生任何影响。

严格来说,您实际上并没有进行适当的原型继承。您可以通过以下方式确认:

dog_b.hasOwnProperty('age'); // => true

这实际上称为 constructor stealing,其中 Dog 窃取了 Animal 的构造函数。 walk 方法虽然在 Animal 的 ctor 上。

这意味着 age 属性 在 Dog 本身而不是 Animal 上。这是为什么?同样,因为您要手动将 Animal 的构造函数上下文建立为 Dog.

的构造函数上下文

编辑:

在 Javascript 中有多种描述和获得继承的方法,由于这不是写书的地方,所以我会很快。

您正在做的事情叫做 Parasitic Combination Inheritance(您不必记住这个词)。这并没有错,它只是获得继承的另一种方式(这只是 Animal.prototype 上的函数的原型)。如果它对你有用,我会说接受它。如果你真的真的想让AnimalageAnimal上,那么你在使用构造函数获取继承时就会遇到问题

这样做的一种方法是:

function inherit(o){
    function F(){}
    F.prototype = o;
    return new F();
}

var foo = {
    name: 'some'
}

var bar = inherit(foo); // bar.name refers to the object on foo

如您所见,原型继承通常用于对象文字(想想 angular 的作用域对象)。