1.类式继承
// 类式继承
// 声明父类
function SuperClass() {
this.superValue = true;
}
// 为父类添加共有方法
SuperClass.prototype.getSuperValue = function() {
return this.superValue;
};
// 声明子类
function SubClass() {
this.subValue = false;
}
// 继承父类
SubClass.prototype = new SuperClass();
// 为子类添加共有方法
SubClass.prototype.getSuperValue = function() {
return this.subValue;
}
注意:类式继承有两个问题:
- 父类的共有属性如果是引用类型,就会在子类中被所有实例共用,因此一个子类的实例更改原型从父类构造函数中继承来的共有属性就会直接影响到其他子类.
- 由于子类实现的继承是靠prototype对父类的实例化实现的,因此在创建父类的时候,是无法向父类传递参数的
2.构造函数继承
// 构造函数继承
// 声明父类
function SuperClass(id) {
// 引用类型共有属性
this.books = ['JavaScript', 'html', 'css'];
// 值类型共有属性
this.id = id;
}
// 父类声明原型方法
SuperClass.prototype.showBooks = function() {
console.log(this.books);
};
// 声明子类
function SubClass(id) {
SuperClass.call(this, id);
}
// 继承父类
SubClass.prototype = new SuperClass();
// 为子类添加共有方法
SubClass.prototype.getSuperValue = function() {
return this.subValue;
}
这里,SuperClass.call(this, id)是构造函数继承的精髓,对SuperClass这个函数的调用就是将子类的变量在父类中执行一遍.
缺点
父类的原型方法不会被子类继承,如果想要被子类继承就要把方法放到构造函数里,这样创建的每个实例都会拥有单独的一份代码而不能共用,违反了代码复用的原则.
3.组合继承
// 组合继承
// 声明父类
function SuperClass(name) {
// 值类型共有属性
this.name = name;
// 引用类型共有属性
this.books = ['JavaScript', 'html', 'css'];
}
// 父类声明原型方法
SuperClass.prototype.getName = function() {
console.log(this.name);
};
// 声明子类
function SubClass(name, time) {
// 构造函数式继承父类name属性
SuperClass.call(this, name);
// 子类中新增共有属性
this.time = time;
}
// 类式继承 子类原型继承父类
SubClass.prototype = new SuperClass();
// 为子类添加共有方法
SubClass.prototype.getTime = function() {
return this.time;
}
优点
子类的实例中更改父类继承下来的引用类型属性根本不会影响其他实例,并且子类实例化过程中又可以将参数传递到父类的构造函数,比如name.
缺点
在使用构造函数继承的时候调用了一次父类的构造函数,在实现子类原型的类式继承的时候又调用了一遍父类的构造函数,父类的构造函数被调用了两遍.
4.原型式继承
借助原型prototype可以根据已有对象创建一个新的对象,同时不必创建新的自定义对象类型.
// 原型式继承
function inheritObject(o) {
// 声明一个过渡函数对象
function F() {}
// 过渡对象的原型继承父对象
F.prototype = o;
// 返回过渡对象的一个实例, 该实例的原型继承了父对象
return new F();
}
原型式继承的问题与类式继承的问题一样.
5.寄生式继承
// 寄生式继承
// 声明基对象
var book = {
name: 'js',
alike: ['css', 'html']
}
function createBook(obj) {
// 通过原型继承的方式创建新对象
var o = inheritObject(obj)
// 拓展新对象
o.getName = function() {
console.log(name);
}
// 返回拓展后的新对象
return o;
}
6.寄生组合式继承
/**
* 寄生式继承 继承原型
* 传递参数 subClass 子类
* superClass 父类
*/
function inheritPrototype(subClass, superClass) {
// 复制一份父类的原型
var p = inheritObject(superClass.prototype);
// 修正因为重写子类原型导致子类constructor被修改
p.constructor = subClass;
// 设置子类原型
subClass.prototype = p;
}