很多人反应前两天的内容抽象难懂并且不实用,这是广大前端的共同心声,所以ES6对继承做了优化
本文部分内容参考《ES6标准入门》(第二版)
通过构造函数声明类(其中部分代码使用了es6,但依然是传统的思想)
function HeroES5(name, skill) {
this.name = name
this.skill = skill
}
HeroES5.prototype.doSth = function () {
console.log(`练习${this.skill}`);
}
HeroES5.prototype.sayName = function () {
console.log(`我的名字是${this.name}`);
}
class
在ES6中引入了class(类)的概念,ES6中的class可以看做是一个语法糖,他的绝大部分功能ES5都可以做到,新的class写法是对象原型的写法更加清晰,更像面向对象编程的写法,将上面的demo用ES6来写
class HeroES6 {
constructor(name, skill) {
this.name = name
this.skill = skill
}
doSth() {
console.log(`练习${this.skill}`);
}
sayName() {
console.log(`我的名字是${this.name}`);
}
}
我们分别观察一下他们的数据类型
console.log(typeof HeroES5);//=>function
console.log(typeof HeroES6);//=>function
看来ES6中的class也是函数类型,既然是函数类型就一定有prototype
我们分别观察一下他们的prototype
console.log(HeroES5.prototype);
console.log(HeroES6.prototype);
构造函数中的prototype属性在ES6的“类”上继续存在,事实上,类的所有方法都定义在类的prototype属性上
我们通过类实例化一个对象
const hr = new HeroES6("黄蓉", "打狗棒")
console.log(hr);
上面的栗子中,name和skill是hr的自身属性,(因为定义在this变量上),doSth()和sayName(),是原型对象上的属性,(因为定义在HeroES6类上)
还记得hasOwnProperty吗?回忆一下关于javascript的Object. hasOwnProperty,看我就够了
Object的hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
console.log(hr.hasOwnProperty('name')); //=>true
console.log(hr.hasOwnProperty('skill')); //=>true
console.log(hr.hasOwnProperty('doSth')); //=>false
console.log(hr.hasOwnProperty('sayName')); //=>false
好,关于ES6中的class我们就说这么多,还有很多没有提及的,可以参考这个链接
class的继承
如果ES5的继承让你头晕目眩,那么是时候研究一下ES6的继承了
Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
举一个
//定义一个类
class HeroES6 {
constructor(name, skill) {
this.name = name
this.skill = skill
}
doSth() {
return `练习${this.skill}`
}
sayName() {
return `我的名字是${this.name}`
}
}
//定义一个类,继承了 HeroES6类
class Gj extends HeroES6 {
constructor(name, skill,favourite) {
super(name, skill, favourite)// 调用父类的 constructor(name, skill)
this.favourite = favourite
}
doSth() {
return super.doSth() + this.favourite//调用父类的sayName()
}
}
const gj = new Gj('郭靖','降龙十八掌','吃饭')
console.log(gj);
console.log(gj.doSth())//=>练习降龙十八掌吃饭
console.log(gj.sayName());//=>我的名字是郭靖
输出
我们先定义一个类HeroES6,我们可以称它为父类,
我们又定义了一个Gj类,我们可以称它为子类,该类通过extends关键字,继承了HeroES6类的所有属性和方法
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
如果子类没有定义constructor方法,这个方法会被默认添加,如果手动添加了constructor方法,就一定要调用super方法,否则新建实例时会报错,调用了super后才能使用this关键字
//部分代码省略
class Gj extends HeroES6 {
constructor(name, skill, favourite) {
this.favourite = favourite//不能在super前调用this
super(name, skill, favourite)
}
doSth() {
return super.doSth() + this.favourite
}
}
//部分代码省略
super
关于super阮一峰的ES6说的很详细
我们强调一点
super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。
子类Gj的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。
注意,super虽然代表了父类 HeroES6的构造函数,但是返回的是子类Gj的实例,即super内部的this指的是Gj
ES6的继承使用方法地区简单方便
好了,关于javascript的继承就介绍到这里
写的不错,保持谦虚,继续努力。继承还是比较重要的。