一、原型链继承
让子类的原型对象指向父类实例,当子类实例找不到对应的属性和方法时,就会往它的原型对象,也就是父类实例上找,从而实现对父类的属性和方法的继承
缺点:覆盖子类原有的属性和方法,只能执行父类的属性和方法,无法调用父类的构造函数
function person(name, age){
this.name = name;
this.age = age
this.run = function(){
console.log(name + '学习');
}
}
// 原型链挂载方法
// 多个实例共享原型链的方法
//让子类的原型对象指向父类实例, 这样一来在Child实例中找不到的属性和方法就会到原型对象(父类实例)上寻找
person.prototype.work = function(){
console.log(this.name + '上课');
}
var p1 = new person('小张', 20);
p1.run();
p1.work();
var p2 = new person('小罗', 33);
p2.run();
p2.work();
//输出'小张学习、小张上课、小罗学习、小罗上课'
二、构造函数继承
在子类的构造函数中执行父类的构造函数,并为其绑定子类的this,让父类的构造函数把成员属性和方法都挂到子类this上去
缺点:继承不了父类原型的属性和方法
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function() {
return this.name
}
function Child() { // 子类
Parent.call(this, '小红在上课')
}
const child1 = new Child();
const child2 = new Child();
child1.name = '小罗在跳舞';
console.log(child1.name) // 小罗在跳舞
console.log(child2.name) //小红在上课
三、组合式继承
使用原型链实现对原型方法的继承,借用构造函数来实现对实例属性的继承
function Father(name) {
this.name = name
}
Father.prototype.getName = function() {
return this.name
}
function Son() {
Father.call(this, '三年模拟')
}
Son.prototype = new Father()
Son.prototype.constructor = Son
const son1 = new Son()
const son2 = new Son()
son1.name = '五年高考'
console.log(son1.name) // '五年高考'
console.log(son2.name) // '三年模拟'
四、寄生式组合继承
通过借用构造函数来继承属性,通过原型链的混成形式来继承方法
function Father(name) {
this.name = name
}
Father.prototype.getName = function() {
return this.name
}
function Son() {
Father.call(this, '三年模拟')
}
Son.prototype = Father.prototype //将`指向父类实例`改为`指向父类原型`
Son.prototype.constructor = Son
const son1 = new Son()
const son2 = new Son()
son1.name = '五年高考'
console.log(son1.name) // '五年高考'
console.log(son2.name) // '三年模拟'
五、对象冒充继承
通过call或apply改变this指向,并执行了父类的构造函数
缺点是无法调用原型链方法,只能继承超类的构造函数
function person(name, age){
this.name = name;
this.age = age
this.run = function(){
console.log(name + '跑步');
}
}
function people(name, age){
person.call(this, name, age)
}
var p1 = new people('李四',30);
p1.run();//输出'李四跑步'