![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e672c09f0c902af33501f883497a21ea.png)
1. 类式继承
简单来说就是子类的prototype指向父类的实例。
// 父类
var SuperClass = function() {
this.bookList = ['CSS', 'HTML', 'JavaScript'];
};
SuperClass.prototype.getBookList = function() {
return this.bookList;
}
// 子类
var ChildClass = function(bookType) {
this.bookType = bookType;
}
ChildClass.prototype = new SuperClass();
ChildClass.prototype.getBookType = function() {
return this.bookType;
}
var instance1 = new ChildClass('js');
console.log('instance1:', instance1);
打印instance1:
1.1. 缺点
- 从上方的打印可以看出来,ChildClass 类的原型对象上会继承父类实例的属性,如果某个子类实例修改了从父类实例继承来的属性,可能会对其他子类实例造成影响。
var instance1 = new ChildClass('js');
var instance2 = new ChildClass('css');
instance1.bookList.push('设计模式');
console.log('instance2:', instance2);
控制台打印instance2:
instance2.bookList的值也跟着改变了。
注意:如果使用 = 修改bookList的值,不会造成影响,因为会直接在instance1实例上添加bookList属性并赋值,来屏蔽原型链上的bookList属性。
instance1.bookList = '设计模式';
console.log('instance1:', instance1);
console.log('instance2:', instance2);
控制台打印:
- 类式继承无法给父类传递参数。父类构造函数中的属性无法通过传参来初始化。
2. 构造函数式继承
构造函数式继承就是在子类中直接调用父类。
var SuperClass = function(bookList) {
this.bookList = bookList;
}
SuperClass.prototype.getBookList = function() {
return this.bookList;
}
var ChildClass = function(bookList, type) {
SuperClass.call(this, bookList);
this.type = type;
}
ChildClass.prototype.getBookType = function() {
return this.bookType;
}
var instance = new ChildClass(['CSS', 'HTML', 'JavaScript'], '前端');
console.log('instance:', instance);
控制台打印instance:
2.1. 缺点
- 在子类中调用父类,父类本身的属性和方法会被绑定在子类实例上,但是子类无法引用到父类的原型对象。
3. 组合式继承
组合式继承,顾名思义,就是将上面我们刚刚学过的类式继承和构造函数式继承两种方式组合在一起,已解决两种继承方式分开使用时造成的缺点。
var SuperClass = function(bookList) {
this.bookList = bookList;
}
SuperClass.prototype.getBookList = function() {
return this.bookList;
}
var ChildClass = function(bookList, type) {
SuperClass.call(this, bookList);
this.type = type;
}
ChildClass.prototype = new SuperClass();
ChildClass.prototype.getBookType = function() {
return this.bookType;
}
var instance = new ChildClass(['CSS', 'HTML', 'JavaScript'], '前端');
console.log('instance:', instance);
控制台打印instance:
bookList属性被绑定在了子类实例上,屏蔽了原型对象上的bookList,所以以后子类修改了bookList属性也不会对其他子类实例造成影响。同时还能给父类传参。
3.1 缺点
- 组合继承方式一共调用两次父类的构造函数,造成了性能浪费。
4. 原型式继承
本质上是对类式继承方式的一种封装,并没有解决类式继承方式的问题。
var SuperClass = {
bookList: ['html', 'css', 'js'],
getBookList: function() {
return this.bookList;
}
};
var inheritObject = function(superObject) {
var Fn = function(){};
Fn.prototype = superObject;
return new Fn();
}
var instance = inheritObject(SuperClass);
// 等价于
// var instance = Object.create(SuperClass);
console.log('instance:', instance);
控制台打印instance:
5. 寄生式继承
本质上是对原型模式的一种封装,并且在封装的过程中,对继承的对象进行扩展,如修改属性、增加方法。
var SuperClass = {
bookList: ['html', 'css', 'js'],
getBookList: function() {
return this.bookList;
}
};
var inheritObject = function(superObject) {
var Fn = function(){};
Fn.prototype = superObject;
return new Fn();
}
var createObject = function(superObject, bookType) {
var obj = inheritObject(superObject);
obj.bookType = bookType;
obj.getBookType = function () {
return this.bookType;
}
return obj;
}
var instance = createObject(SuperClass, '前端');
var bookType = instance.getBookType();
console.log('instance:', instance);
console.log('bookType:', bookType);
控制台打印instance、bookType:
6. 寄生组合式继承
var SuperClass = function(bookList) {
this.bookList = bookList;
}
SuperClass.prototype.getBookList = function() {
return this.bookList;
}
var ChildClass = function(bookList, type) {
SuperClass.call(this, bookList);
this.type = type;
}
var inheritProtoType = function(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
inheritProtoType(ChildClass, SuperClass);
ChildClass.prototype.getBookType = function() {
return this.bookType;
}
var instance = new ChildClass(['CSS', 'HTML', 'JavaScript'], '前端');
console.log('instance:', instance);
控制台打印instance:
寄生组合式继承是开发者使用比较多的。
回顾寄生组合式继承。主要就是三点:
- 子类构造函数的__proto__指向父类构造器,继承父类的静态方法
- 子类构造函数的prototype的__proto__指向父类构造器的prototype,继承父类的方法。
- 子类构造器里调用父类构造器,继承父类的属性。