在上一篇文章里介绍了继承,那其中说过一个很关键的东西想要继承子类里里必需先调用一个super
方法。而super
的做用绝对是价值连城!同时super
的做用还有多种,而且跟你的使用环境有关系。javascript
super
被看成函数使用,这种状况是最广泛的,上一篇文章里已经使用过。它有如下几种做用:java
- super做为函数调用时,表明父类的构造函数
- 调用super后,this会被改为子类
- 只能用在构造函数里,用在其它地方报错
{ class Father{ constructor(){ console.log(new.target.name); } } class Son extends Father{ constructor(){ super(); this.a=10; //这里的this指向,Son的实例 } method(){ //super() 报错,只能用在constructor里 } } new Father(); //Father(new.target返回Father类) new Son(); //Son(new.target返回Son子类) console.log(new Son().a); //10 this指向被修改为了子类的实例 }
子类里面并无写console.log
,可是发现生成子类实例后,控制台里有输出。说明:super
其实至关于执行了父级的constructor
方法。同时弹出的结果是指向了子类,又说明虽然调用的是父类的构造函数,可是调用完后会指向子类,this
指向也被改为了子类的实例。其实supe
的做用至关于执行Father.prototype.constructor.call(this)
;segmentfault
super
也能够被看成对象使用,被看成对象使用的时候状况有些复杂,跟上面是彻底不同的,同时又按使用环境分为了两种状况。浏览器
- 在普通方法中,指向父类的原型对象
* 只能调用原型里的东西 * 若是调用的是方法,那方法内部this指向子类实例 * 若是用super去添加属性的话,super就是this(实例)
- 在私有方法中,指向父类,而不是父类的原型
* 若是调用的是方法,那方法内部this指向子类而不是子类实例
此时切记用super去获取跟设置时的指向彻底不同函数
{ class Father{ constructor(){ this.a='父类实例的a'; this.b='父类实例的b'; } showB(){ console.log(`这是父类身上的共享方法,而且会弹出${this.b}`); } static showB(){ //私有方法能够与上面的方法重名 console.log(`这是父类身上的私有方法,而且会弹出${this.b}`); } } Father.prototype.a='父类原型的a'; //在原型身上的添加一个属性a class Son extends Father{ constructor(){ super(); //这里的super是个方法,做用为引入父类的构造函数(看成函数使用) this.b='子类实例的b'; //此处声明:请按注释标的序号顺序执行代码 // /* * 三、super设置属性 * 一、用super设置属性的话,super就表明当前环境的this。而当前环境为子类的constructor,因此此时的super表明的就是子类的实例对象 * 二、此时下面的showB()方法弹出的内容为"这是父类身上的共享方法,而且会弹出super就是this"是由于,若是super为this的话,那就与上面那段代码重复了,后面覆盖前面 * */ super.b='super就是this'; /* * 四、super获取属性 * 一、此时super的做用是获取属性,它依然指向父类的原型对象因此下面这句话至关于console.log(Father.prototype.b);因此结果为undefined。虽然在上面定义了super.b那也不会改变super的指向 */ console.log(super.b); //undefined /* * 一、这里的super是一个对象,由于constructor是个普通对象 * 一、super指向父类的原型对象,调用的是Father的共享方法showB() * 二、showB方法里的this指向子类的实例,取的是Father的constructor里定义的b */ super.showB(); //这是父类身上的共享方法,而且会弹出子类实例的b //二、super获取属性 console.log(super.a); //父类原型的a 再次验证只能调用原型上的东西。原型上与constructor里都有个a,可是调的是原型上的 } } Son.b='子类的私有属性b'; new Son(); }
此时切记用super的用法与在普通方法中的用法彻底相反this
{ class Father{ constructor(){ this.b='父类实例的b'; } showB(){ console.log(`这是父类身上的共享方法,而且会弹出${this.b}`); } static showB(){ //这是个私有方法,与上面的方法重名是能够的 console.log(`这是父类身上的私有方法,而且会弹出${this.b}`); } } Father.prototype.b='父类原型的b'; //在原型身上的添加一个属性b class Son extends Father{ constructor(){ super(); this.b='子类实例的b'; } /* * 一、这里的super是在私有方法里调用,因此指向父类,调用的是Father里定义的static showB方法 * 二、此方法里的this指向被改为了子类,弹出的b是子类的私有属性b */ static log(){ super.showB(); } } Son.b='子类的私有属性b'; Son.log(); //这是子类身上的私有方法,而且会弹出子类的私有属性b }
super在用的时候必需指定它的类型,否则不清不楚的去用,浏览器会给你报错!prototype
{ class Father{}; class Son extends Father{ constructor(){ super(); //这个是做为函数 //console.log(super); //报错 那这个super它是个什么呢?它本身矛盾了,浏览器迷茫了~ console.log(super.a); //这个是做为对象 } } }
下一篇,实战!code