以以下需要继承的父类为例:
// 定义一个动物类
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();
// 创建猫的实例化对象
new Cat();
构造继承:(没用到原型) ( ✭✭)
- 核心: 使用父类的构造函数来增强子类实例, 等于是复制父类实例的属性给子类
- 特点:
- 子类实例不共享父类的引用属性
- 创建实例时,可以向父类传递参数
- 可以实现多继承
- 缺点:
- 只能继承父类的实例的属性和方法, 无法继承父类的原型的属性和方法
- 无法实现函数复用, 每个子类都有父类实例函数的副本, 影响性能
// 定义一个猫类
function Cat(name) {
// 使用call或apply调用父类的构造函数传递this或this和参数
Animal.call(this);
this.name = name || 'Tom';
}
// 猫的实例化对象
new Cat('xiaobai');
实例继承: ( ✭✭✭)
// 定义一个猫类
function Cat(name) {
// 使用call或apply调用父类的构造函数传递this或this和参数
Animal.call(this);
this.name = name || 'Tom';
}
// 猫的实例化对象
new Cat('xiaobai');
- 核心: 为父类实例添加新特性,作为子类实例返回
- 特点: 不限制调用方式, 不使用new关键字调用构造函数具有相同的效果
- 缺点:
- 实例是父类的实例
- 不支持多继承
function Cat(name) {
// 把父类实例作为子类构造函数的返回值
var instance = new Animal();
instance.name = name || 'Tom';
return instance;
}
//创建对象
new Cat();
拷贝继承: (✭ )
function Cat(name) {
// 把父类实例作为子类构造函数的返回值
var instance = new Animal();
instance.name = name || 'Tom';
return instance;
}
//创建对象
new Cat();
- 核心: 把父类的所有属性和方法拷贝到子类的原型上
- 特点: 支持多继承
- 缺点:
- 效率低, 内存占用大
- 无法获取父类不可枚举的方法
function Cat(name) {
//把父类的原型拷贝到子类的原型上
var animal = new Animal();
for(var p in animal){
cat.prototype[p] = animal[p];
}
}
//创建对象
new Cat();
组合继承: (✭✭✭✭ 仅多消耗了一点内存)
- 核心: 结合构造继承和原型链继承
- 特点:
- 继承父类实例的属性和方法,也继承原型的属性和方法
- 既是子类实例, 也是父类实例
- 不存在引用共享问题
- 可传参
- 函数可复用
- 缺点:
- 调用了两次父类构造函数, 生成了两份实例
function Cat(name) {
// 构造继承
Animal.call(this);
}
// 原型链继承
Cat.prototype = new Animal();
//创建对象
new Cat();
寄生组合式继承: (✭✭✭✭✭)
- 核心: 通过寄生方式, 避免组合继承的缺点。不会初始化两次父类
- 特点: 比较完美(可以实现多继承, 完美的继承了父类的属性方法, 及父类原型)
- 缺点: 实现比较复杂
function Cat(name) {
// 构造继承
Animal.call(this);
}
(function () {
//创建一个空白类
var Super = function (){};
//将空白类构造函数的原型对应父类构造函数的原型
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
})();
//创建对象
new Cat();