JavaScript 类继承
介绍
继承是面向对象编程中的核心概念之一,允许我们创建基于现有类的新类,从而重用代码并建立对象之间的层次关系。在ES6引入class
关键字之前,JavaScript主要通过原型链实现继承。现在,ES6的类语法让继承变得更加直观和易于使用,虽然底层仍然是基于原型的实现。
本教程将帮助你理解JavaScript中的类继承机制,掌握extends
关键字的使用,以及处理继承过程中常见的挑战。
类继承的基本语法
在JavaScript中,我们使用extends
关键字来创建一个继承自另一个类的子类:
class Parent {
constructor(name) {
this.name = name;
}
greet() {
return `Hello, I am ${this.name}`;
}
}
class Child extends Parent {
constructor(name, age) {
super(name); // 调用父类构造函数
this.age = age;
}
greet() {
return `${super.greet()} and I am ${this.age} years old`;
}
}
// 创建实例
const parent = new Parent('Alice');
const child = new Child('Bob', 5);
console.log(parent.greet()); // 输出: "Hello, I am Alice"
console.log(child.greet()); // 输出: "Hello, I am Bob and I am 5 years old"
备注
super
关键字有两种用法:
- 在构造函数中调用
super()
,代表调用父类的构造函数 - 在方法中使用
super.方法名()
,代表调用父类的同名方法
继承中的关键概念
1. super关键字
super
是继承中的一个重要关键字,它有两个主要用途:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} makes a noise`;
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类构造函数
this.breed = breed;
}
speak() {
return `${super.speak()}, specifically a bark!`; // 调用父类方法
}
getDetails() {
return `${this.name} is a ${this.breed}`;
}
}
const dog = new Dog('Rex', 'German Shepherd');
console.log(dog.speak()); // 输出: "Rex makes a noise, specifically a bark!"
console.log(dog.getDetails()); // 输出: "Rex is a German Shepherd"
警告
在子类的构造函数中,必须先调用super()
才能使用this
关键字,否则会抛出ReferenceError
。
class Child extends Parent {
constructor(name) {
console.log(this); // 错误:在调用super()之前引用this
super(name);
}
}
2. 方法覆盖
子类可以覆盖(重写)父类中的方法,以提供特定于子类的行为:
class Vehicle {
constructor(type) {
this.type = type;
}
getDescription() {
return `This is a ${this.type}`;
}
}
class Car extends Vehicle {
constructor(make, model) {
super('car');
this.make = make;
this.model = model;
}
getDescription() {
// 覆盖父类方法
return `This is a ${this.make} ${this.model} ${this.type}`;
}
}
const myCar = new Car('Toyota', 'Corolla');
console.log(myCar.getDescription()); // 输出: "This is a Toyota Corolla car"
3. 属性继承
子类自动继承父类的所有属性:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class Employee extends Person {
constructor(name, age, jobTitle) {
super(name, age);
this.jobTitle = jobTitle;
}
}
const employee = new Employee('John', 30, 'Developer');
console.log(employee.name); // 输出: "John" (继承自Person)
console.log(employee.age); // 输出: 30 (继承自Person)
console.log(employee.jobTitle); // 输出: "Developer" (Employee自己的属性)
类继承的复杂场景
多层继承
JavaScript支持多层继承,即一个类可以继承自另一个子类:
class Animal {
constructor(name) {
this.name = name;
}
eat() {
return `${this.name} is eating.`;
}
}
class Mammal extends Animal {
constructor(name) {
super(name);
}
warmBlooded() {
return `${this.name} is warm-blooded.`;
}
}
class Dog extends Mammal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() {
return `${this.name} is barking!`;
}
}
const myDog = new Dog('Buddy', 'Golden Retriever');
console.log(myDog.eat()); // 来自Animal类
console.log(myDog.warmBlooded()); // 来自Mammal类
console.log(myDog.bark()); // 来自Dog类
输出:
Buddy is eating.
Buddy is warm-blooded.
Buddy is barking!