继承:原型和类

143 阅读1分钟

基于原型的继承:

在 JavaScript 中,所有的对象都有一个隐藏的 __proto__ 属性,指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(proto),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。 我们可以使用 obj.__proto__ 访问对象的原型;如果我们想要读取 obj 的一个属性或者调用一个方法,并且它不存在,那么 JavaScript 就会尝试在原型中查找它。

代码示例:

let animal = { 
    eats: true 
}; 
let rabbit = {
    jumps: true
}; 
rabbit.__proto__ = animal; // 设置 rabbit的原型为animal
alert( rabbit.eats ); // true 
//当alert试图读取rabbit.eats时,因为它不存在于rabbit中
//JavaScript 会顺着Prototype引用,在animal中查找
alert( rabbit.jumps ); // true

基于类的继承:

类继承是一个类扩展另一个类的方式,类通过extend关键字实现继承。

class Animal { 
    constructor(name) { 
        this.speed = 0; 
        this.name = name; 
    } 
    run(speed) { 
        this.speed = speed; 
        alert(`${this.name} runs with speed ${this.speed}.`); 
    }
    stop() { 
        this.speed = 0; 
        alert(`${this.name} stands still.`); 
    } 
} 
let animal = new Animal("My animal");
class Rabbit extends Animal {
    hide() { 
        alert(`${this.name} hides!`); 
    } 
} 
let rabbit = new Rabbit("White Rabbit"); 
rabbit.run(5); // White Rabbit runs with speed 5. rabbit.hide(); // White Rabbit hides!

class Rabbit 继承自 class Animal,Class Rabbit 的对象可以访问例如 rabbit.hide() 等 Rabbit 的方法,还可以访问例如 rabbit.run() 等 Animal 的方法。

当重写一个constructor时:

  • 在使用 this 之前,我们必须在 Child 的 constructor 中将父 constructor 调用为 super()
class Animal {
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
}
class Rabbit extends Animal {
  constructor(name, earLength) {
    super(name);
    //如果不按照这么写,而是
    //this.speed = 0
    //this.name = name
    //会报错,派生的 constructor 必须调用 super才能执行其父类的 constructor,否则 `this` 指向的那个对象将不会被创建
    this.earLength = earLength;
  }
}

let rabbit = new Rabbit("White Rabbit", 10);
alert(rabbit.name); // White Rabbit
alert(rabbit.earLength); // 10