定义一个父类
function Father(name){
// 属性
this.name = name || 'father';
// 实例方法
this.sayName = function(){
console.log(this.name);
}
}
// 实例原型方法
Father.prototype.age = 18;
Fatcher.prototype.sayAage = function(){
console.log(this.age);
}
一、原型链继承
将父类的实例作为子类的原型
function Son(){
}
Son.prototype = new Father();
Son.prototype.constructor = Son;
优点:
- 简单易操作
- 父类新增的方法或属性子类都能接收到
缺点:
- 没有办法像父类传参
- 无法实现多继承
- 所有的子类的实例原型都共享同一个超类的属性和方法
二、构造继承
function Son(name){
Father.call(this, '要向父类传递的参数');
this.name = name || 'son';
}
优点:
- 继承父类的属性和方法,能够像父类传递参数
- 解决了所有子类实例共享父类属性引用问题
- 可以实现多继承
缺点:
- 无法继承父类原型上的属性和方法
三、组合继承
结合原型链继承和构造继承
function Son(name){
Father.call(this, '要向父类传递的参数');
this.name = name || 'son';
}
Son.prototype = new Father();
Son.prototype.constructor = Son;
优点:
- 解决了原型链继承和构造继承缺点
缺点:
- 调用了两次父类构造函数,生成了两份实例,只是子类的属性覆盖了超类的属性
四、原型式继承
function createObj(obj){
function f(){};
f.prototype = obj;
return new f();
}
优点:
直接通过继承一个对象生成一个对象
缺点:
不是类式继承,而是原型式基础
五、寄生式继承
function createObj(obj){
function f(){};
f.prototype = obj;
return new f();
}
function cloneObj(cloneObj){
const f = createObj(cloneObj);
f.prototype = '...要给当前函数赋值的属性或方法';
return f;
}
就是原型式继承的一种扩展
六、寄生组合式继承
通过寄生方式,砍掉父类的实例属性,避免了组合继承生成两份实例的缺点
function Son(name){
Father.call(this, '要向父类传递的参数');
this.name = name || 'son';
}
Son.prototype = Object.create(Father.prototype);
Son.prototype.cunstructor = Son;
优点:
比较完美
缺点:
不通过Object.create()
方法实现起来会很复杂
七、ES6–class继承
class Son extend Father {
constructor(name){
super(name);
this.name = name || 'son';
}
}
使用 class + extend 实现继承