继承:一个类继承另一个类(一个构造函数继承另一个构造函数) 。 子类继承父类,子类会有父类所有的方法。
Es5:es5中使用构造函数;一个构造函数继承另一个构造函数。
Es6:es6中引入了class类的概念;子类继承父类。
es5继承:
es5有三种继承方法,分别是:借用构造函数继承、原型链继承、混合继承。
首先介绍以下Es5 的借用构造函数继承:
先创建一个父函数,添加属性和方法
function Person(chick, amo) {
console.log(this) //此时Person的this指向Person {}对象
//添加属性
this.chick = chick
this.amo = amo
}
// 在Person原型上添加eat()方法
Person.prototype.eat = function (name = '大黄') {
console.log(name + '吃了' + this.amo + '个' + this.chick)
}
let per = new Person('鸡腿', '5')
per.eat() //执行结果=>大黄吃了5个鸡腿
创建第二个函数-子函数,继承Person
function sPerson(name, age) {
console.log(this) //sPerson{}
//使用call()方法,改变Person中this指向,把sPerson参数传给Person;实现继承
//也可以使用apply(); Person.apply(this, [name, age])
Person.call(this, name, age)
}
let xiaohong = new sPerson('小红', 16)
//此时可以在xiaohong中使用Person中的属性
console.log(xiaohong.chick + '今年' + xiaohong.amo + '岁') //执行结果=>小红今年16岁
缺点:无法使用父函数在原型上添加的属性和方法
其次介绍以下 Es5 的原型链继承
借用上面创建的父函数,修改子函数的原型指向父函数;当子函数使用一个属性的时候可以去父函数的原型里面找。
// 子函数
function sPerson(name, age) {
console.log(this) //sPerson{}
this.eat('小红') //可以调用Person的eat()方法,执行结果=>小红吃了5个鸡腿
}
// 修改子函数的原型指向父函数
sPerson.prototype = per
let xiaohong = new sPerson('小红', 16)
console.log(xiaohong.chick + '今年' + xiaohong.amo + '岁') //鸡腿今年5岁
缺点:使用原型链继承可以在子函数中用到父函数原型上的方法,但是父函数的属性是固定的,无法由子函数传参修改
混合继承:结合借用构造函数继承和原型链继承,得到一个最优解
同时使用借用构造函数和原型链继承,就可以继承到父函数的属性和方法;具体代码如下
// 子函数
function sPerson(name, age) {
console.log(this) //sPerson{}
// 修改父函数this指向,子函数参数传递给父函数
Person.call(this, name, age)
this.eat('小红') //可以调用Person的eat()方法,执行结果=>小红吃了16个葡萄
}
// sPerson原型指向父函数
sPerson.prototype = per
let xiaohong = new sPerson('葡萄', 16)
console.log('这盘' + xiaohong.chick + '有' + xiaohong.amo + '颗') //执行结果=>这盘葡萄有16颗
Es6继承
在Es6中新增了类,类就是封装了es5 构造函数和原型的写法。
es6继承的底层其实就是采用的混合继承,只是封装了,提供了一个新的写法。具体代码如下
//父类
class Person {
constructor(chick, amo) {
this.chick = chick
this.amo = amo
}
eat(name = '大黄') {
console.log(name + '吃了' + this.amo + '个' + this.chick)
}
}
//使用extends关键字,子类 继承(extends) 父类
class sPerson extends Person{
}
let xiaohong = new sPerson('小红', 16)
// 继承了父类属性
console.log(xiaohong.chick + '今年' + xiaohong.amo + '岁') //执行结果=>小红今年16岁
// 继承了父类方法
xiaohong.eat() //执行结果=>大黄吃了16个小红
可以在子类中添加自己的属性和方法,在添加之前要做的一个事情:super(...args)在子类构造函数中向父类传递子类参数
class sPerson extends Person{
constructor(name, age) {
//把子类参数传递给父类;当子类不添加构造函数constructor的时候,底层会默认添加一个和父类相同的构造函数
//super(name,age)等同Person.call(this,name,age)
super(name,age)
//子类添加自己的属性
this.ice = '冰淇淋'
}
//子类添加自己的方法
eat(){
// 当不调用super.eat()父类的eat()方法时,子类的eat()方法就会覆盖掉父类的eat()方法
super.eat() //大黄吃了16个小红
console.log(this.chick + '吃了' + this.amo + '个'+ '冰淇凌') //小红吃了16个冰淇凌
}
}
let xiaohong = new sPerson('小红', 16)
xiaohong.eat() //执行结果=>大黄吃了16个小红 /n 小红吃了16个冰淇凌
都看到这了,给个赞再走呗👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍👍