类继承方式
// 定义父类
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound.`);
}
}
// 定义子类
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() {
console.log(`${this.name} barks.`);
}
}
// 使用子类
let myDog = new Dog('Buddy', 'Golden Retriever');
myDog.speak();
myDog.bark();
构造函数继承方式
// 定义父构造函数
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound.`);
};
// 定义子构造函数
function Dog(name, breed) {
Animal.call(this, name);
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log(`${this.name} barks.`);
};
// 使用子构造函数
let myDog = new Dog('Buddy', 'Golden Retriever');
myDog.speak();
myDog.bark();
差异分析
- 实现原理
- 类继承:ES6 类继承基于原型链,通过
extends
关键字声明子类继承自父类,使用 super
调用父类构造函数,本质上还是原型继承的语法糖。
- 构造函数继承:通过
call
或 apply
方法在子类构造函数中调用父类构造函数,以借用父类的属性,然后通过 Object.create
来设置子类的原型为父类原型的实例,从而实现方法的继承。
- 语法
- 类继承:语法简洁明了,使用
class
关键字定义类,extends
实现继承,super
调用父类构造函数和访问父类方法,更符合面向对象编程习惯。
- 构造函数继承:使用函数定义构造函数,通过
call/apply
借用属性,通过原型赋值实现方法继承,语法相对复杂。
- 使用场景
- 类继承:适用于现代 JavaScript 开发,尤其是在需要清晰表达继承关系和面向对象结构的场景,如大型应用开发、框架设计等。
- 构造函数继承:在 ES6 之前广泛使用,对于一些需要兼容旧环境或者对性能优化有特定需求(如避免原型链上不必要的属性)的场景仍有一定价值。