1. 原型继承
原型继承是 JavaScript 中最基础的继承形式。每个对象都有一个内部属性 __proto__
,指向其构造函数的原型对象。这意味着子对象可以访问父对象的属性和方法,而无需显式继承它们。
// 创建父构造函数
function Person(name) {
this.name = name;
}
// 创建子构造函数
function Student(name, grade) {
// 调用父构造函数
Person.call(this, name);
this.grade = grade;
}
// 设置子对象的原型为父对象的原型
Student.prototype = Object.create(Person.prototype);
const student = new Student("John", "A");
console.log(student.name); // John
console.log(student.grade); // A
2. 类继承
ES6 引入了 class
关键字,支持更简洁的类继承语法。类继承通过 extends
关键字实现,子类继承父类的所有属性和方法。
class Person {
constructor(name) {
this.name = name;
}
}
class Student extends Person {
constructor(name, grade) {
super(name); // 调用父类的构造函数
this.grade = grade;
}
}
const student = new Student("John", "A");
console.log(student.name); // John
console.log(student.grade); // A
3. 构造函数盗用
构造函数盗用是一种通过将父构造函数的属性和方法复制到子构造函数中来实现继承的技术。
function Person(name) {
this.name = name;
}
function Student(name, grade) {
// 调用父构造函数
Person.call(this, name);
// 复制父构造函数的属性和方法
for (const key in Person.prototype) {
if (Person.prototype.hasOwnProperty(key)) {
this[key] = Person.prototype[key];
}
}
this.grade = grade;
}
const student = new Student("John", "A");
console.log(student.name); // John
console.log(student.grade); // A
4. 混合继承
混合继承结合了原型继承和构造函数盗用两种技术,允许子类继承父类的属性和方法,同时解决构造函数盗用带来的问题。
function Person(name) {
this.name = name;
}
function Student(name, grade) {
// 调用父构造函数
Person.call(this, name);
// 复制父构造函数的属性和方法
for (const key in Person.prototype) {
if (Person.prototype.hasOwnProperty(key)) {
this[key] = Person.prototype[key];
}
}
// 设置子对象的原型为父对象的原型
this.__proto__ = Person.prototype;
this.grade = grade;
}
const student = new Student("John", "A");
console.log(student.name); // John
console.log(student.grade); // A
5. 选择最佳继承模式
选择最合适的继承模式取决于具体的需求和应用程序的架构。
- 原型继承:适用于创建简单、轻量级的对象,不需要显式继承。
- 类继承:使用最流行的 ES6 语法,提供简洁、类型安全的继承。
- 构造函数盗用:在早期版本的 JavaScript 中使用,但可能会产生问题。
- 混合继承:解决构造函数盗用的问题,但比原型继承更复杂。
总结
JavaScript 继承通过允许对象共享属性和方法,使开发者能够创建可复用、可扩展的代码。理解和掌握不同的继承模式对于构建健壮、面向对象的应用程序至关重要。