目录
1.原型链继承
让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例具有该实例的属性。
function Parent(){
this.Show = true
this.info = {
name:'abc',
age:18
}
}
//在它的原型上添加一个方法
Parent.prototype.getInfo = function(){
console.log(this.Show)
console.log(this.info)
}
function Child(){
}
//子类的原型等于父类的实例
Child.prototype = new Parent()
let Child1 = new Child()
Child1.info.gender = '男'
Child1.getInfo() //{name:'abc' , age:18 , gender:'男'} true
优点:写法便捷,容易理解。
缺点:对象实例共享所有继承的属性和方法,无法向父类构造函数传参。
2.构造函数继承
在子类型构造函数的内部调用父类型构造函数,使用apply()或call()方法将父对象的构造函数绑定在子对象上。
function Parent(gender){
this.info = {
name:'abc',
age:18,
gender:gender
}
}
function Child(gender){
Parent.call(this,gender)
}
let Child1 = new Child('男')
console.log(Child1.info) //{name:'abc' , age:18 , gender:'男'}
优点:解决了原型链实现继承不能传参的问题和父类的原型共享问题。
缺点:方法都在构造函数中定义,无法实现函数复用。在父类的原型中定义的方法,对子类而言是不可见的,所有的类型都只能使用构造函数模式。
3.组合式继承
将原型链和构造函数这两种继承方法组合到一起,使用原型链对原型属性和方法进行继
承;使用构造函数对实例属性进行继承,结合了二者的特点。
function Person(gender){
console.log('我执行了')
this.info = {
name:'abc',
age:18,
gender:gender
}
}
//使用了原型链继承原型上的属性和方法
Person.prototype.getInfo = function(){
console.log(this.info.name,this.info.age) //abc 18
}
function Child(gender){
//使用了构造函数传递参数
Person.call(this,gender)
}
Child.prototype = new Person()
let Child1 = new Child('男')
Child1.getInfo()
console.log(Child1.info) //{name:'abc',age:18,gender:'男'}
优点:结合了二者的特点。
缺点:无论什么情况下都会调用两次父类构造函数。一次是在创建子类原型的时候,另一次是在子类构造函数的内部。
4.ES6中的Class类继承
Class通过extends关键字实现继承,原理是先创造出父类的this对象,然后使用子类的构造函数修改this。
子类的构造方法中必须调用super方法,只有在调用super()之后才能使用this,因为子类的this对象是继承父类的this对象,然后对其进行加工,而super方法表示的是父类的构造函数,用来创建父类的this对象。
class Animal{
constructor(kind){
this.kind = kind
}
getKind(){
return this.kind
}
}
//继承
class Cat extends Animal{
constructor(name){
//子类的构造方法中必须先调用super方法
super('cat')
this.name = name
}
getCatInfo(){
console.log(this.name + ':' + super.getKind())
}
}
const cat1 = new Cat('biu')
cat1.getCatInfo() //biu:cat
优点:语法简单,操作方便。
缺点:浏览器兼容性差,并不是所有浏览器都支持class关键字。