1. 原型继承
原型继承是通过让一个对象作为另一个对象的原型来实现继承。在 JavaScript 中,每个对象都有一个指向其原型对象的内部 [[Prototype]] 属性,可以通过设置对象的 [[Prototype]] 属性来实现继承。
// 定义一个父类对象
function Animal() {
this.type = 'Animal';
}
Animal.prototype.say = function() {
console.log('I am a ' + this.type);
};
// 定义一个子类对象
function Cat() {
this.type = 'Cat';
}
Cat.prototype = new Animal();
// 创建一个 Cat 对象
var cat = new Cat();
cat.say(); // 输出 "I am a Cat"
在上面的示例中,我们定义了一个父类对象 Animal 和一个子类对象 Cat。通过将 Cat.prototype 设置为一个 Animal 对象的实例,我们实现了 Cat 对象对 Animal 对象的继承。
2. 借用构造函数继承
借用构造函数继承是通过在子类构造函数中调用父类构造函数来实现继承。在子类构造函数内部使用 call() 或 apply() 方法调用父类构造函数,并将子类对象作为 this 对象传入,以实现父类构造函数中的属性和方法的继承。
// 定义一个父类对象
function Animal(type) {
this.type = type;
}
Animal.prototype.say = function() {
console.log('I am a ' + this.type);
};
// 定义一个子类对象
function Cat(type) {
Animal.call(this, type);
}
// 创建一个 Cat 对象
var cat = new Cat('Cat');
cat.say(); // 报错,因为 Cat 对象并没有继承 Animal 对象的原型
在上面的示例中,我们定义了一个父类对象 Animal 和一个子类对象 Cat。在子类构造函数中调用了父类构造函数 Animal.call(this, type),以实现属性的继承。但是由于 Cat 对象并没有继承 Animal 对象的原型,因此调用 cat.say() 方法会报错。
3. 组合继承
组合继承是通过将原型继承和借用构造函数继承结合起来实现继承。在子类构造函数内部使用 call() 或 apply() 方法调用父类构造函数来实现属性的继承,并通过将子类原型对象设置为一个父类对象的实例来实现方法的继承。
// 定义一个父类对象
function Animal(type) {
this.type = type;
}
Animal.prototype.say = function() {
console.log('I am a ' + this.type);
};
// 定义一个子类对象
function Cat(type) {
Animal.call(this, type);
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
// 创建一个 Cat 对象
var cat = new Cat('Cat');
cat
总的来说,三种继承方式都有各自的优点和缺点,具体使用时需要根据实际情况选择适合的继承方式。如果需要继承多个对象的属性和方法,可以使用原型继承;如果需要在子类构造函数中定义独立的属性和方法,可以使用借用构造函数继承;如果既需要继承父类原型对象的属性和方法,又需要在子类构造函数中定义独立的属性和方法,可以使用组合继承。