下面介绍 4 种常见继承方式:原型继承、构造继承、组合继承、组合寄生式继承。下面是一个父类的声明:
function Animal (name) {
// 属性
this.name = name || 'Animal';
// 实例方法
this.sleep = function(){
console.log(this.name + ' 正在睡觉!');
}
}
// 原型方法
Animal.prototype.eat = function(food) {
console.log(this.name + ' 正在吃 ' + food);
};
将父类的实例作为子类的原型。
function Cat(){}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat'; //如果要为原型添加属性,必须一个个添加
Cat.prototype.constructor = Cat; // 修复构造函数指向
// Test Code
var cat = new Cat();
console.log(cat.name); // cat
cat.sleep(); // cat 正在睡觉
cat.eat('fish'); // cat 正在吃 fish
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
使用父类的构造函数来增强子类实例(没用到原型),但是这样只是借用了构造函数,没有构造我们想要的原型链。
function Cat(name){
Animal.call(this,name);
this.name = name || 'Tom';
}
// Test Code
var cat = new Cat("cat");
console.log(cat.name); // cat
cat.sleep(); // cat 正在睡觉
cat.eat('fish'); // 找不到 eat 函数
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
使用上述两种方法的组合,唯一缺点就是调用了两次父类构造函数
function Cat(name){
Animal.call(this,name);
this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat; // 修复构造函数指向
// Test Code
var cat = new Cat("cat");
console.log(cat.name); // cat
cat.sleep(); // cat 正在睡觉
cat.eat('fish'); // cat 正在吃 fish
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
通过一个中介函数temp()
,拷贝 Animal 类的原型。其他实现与组合继承相同。
function Cat(name){
Animal.call(this,name);
}
var temp = function(){};
temp.prototype = Animal.prototype;
Cat.prototype = new temp();
Cat.prototype.constructor = Cat; // 修复构造函数指向
// Test Code
var cat = new Cat("cat");
console.log(cat.name); // cat
cat.sleep(); // cat 正在睡觉
cat.eat('fish'); // cat 正在吃 fish
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
使用Object.create()
更简洁地进行原型复制。
function Cat(name){
Animal.call(this,name);
}
/*
var temp = function(){};
temp.prototype = Animal.prototype;
Cat.prototype = new temp();
*/
Cat.prototype = Object.create(Animal.prototype); // 这行代码的作用即为上述三行代码
Cat.prototype.constructor = Cat; // 修复构造函数指向
- 类属性用 this 界定
- 类方法用 prototype 对象界定
- 继承属性,使用
call()
函数传递 this 对象和构造参数 - 继承方法,使用
Object.create()
连接父类和子类的原型 - 始终将子类构造函数设置成自身