【每日一题NO.52】ES6 类继承中 super 的作用
人生苦短,总需要一点仪式感。比如学前端~
概念
super 当作函数
super 当做对象
普通方法中指向父类的原型对象
静态方法中指向父类本身
super中的this指向(总结)
概念
super 关键词用于访问和调用一个对象的父对象上的函数。
super 既可以当做函数使用,也可以当做对象使用
super([arguments]); // 调用父对象/父类 的构造函数
super.functionOnParent([arguments]); //调用 父对象/父类 上的方法
super 当作函数
super 作为函数调用时,代表父类的构造函数。
ES6 要求,子类的构造函数必须执行一次 super 函数
class Father {}
class Son extends Father {
constructor() {
super(); // 子类实现继承时,构造函数必须写super函数调用
}
}
super代表父类的构造函数 被调用时,有以下几点需要注意:
super 返回的对象是子类的实例。super 内部的 this 指的是 Son 的实例,这里调用 super()
相当于Father.prototype.constructor.call(this)
这么写。super 作为构造函数时,必须在使用 this 关键词之前使用,否则会报错 super()
调用,只能用在子类构造函数中,用在其他地方会报错
super 当做对象
super 作为对象时,有两种情况:
在普通方法中,指向父类的原型对象; 在静态方法中,指向父类本身
普通方法中指向父类的原型对象
super 指向的是父类原型对象,能获取父类原型对象上面的属性和方法,不能获取父类实例上的属性和方法 通过 super 调用父类原型对象上的方法时,父类原型对象上方法内部的 this 指向子类实例
class Father {
constructor() {
this.name = "fatherName";
}
print() {
console.log(this.name); // 代表父类构造函数使用的super(),函数内部的this指向子类实例
}
}
class Son extends Father {
constructor() {
super();
this.name = "sonName";
}
printSon() {
super.print(); // print内部this指向Son的实例化对象
}
}
let son = new Son();
son.printSon(); //'sonName'
/* 解析
Son.printSon函数中,super.print() 虽然相当于调用的是“Father.prototype.print()”,
但是Father.prototype.print()内部的 this 指向子类 Son 的实例,所以实际输出的是“sonName”而不是“fatherName”。
也就是说,printSon函数内实际上执行的是“super.print.call(this)”。
*/
通过 super 来对某个属性赋值,这时 super 就是 子类this,赋值的属性会变为子类实例son的属性
// 阮一峰 es6文档的例子
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3; // 相当于 this.x = 3
console.log(super.x); // undefined 父类没有增加x属性
console.log(this.x); // 3 子类的x属性被改变
}
}
let b = new B();
console.log(b.x); // 3
静态方法中指向父类本身
因为在静态方法中使用就跟原型没关系了,所以不代表原型也不代表实例对象。
在静态方法中,super 对象指的是父类,而不是父类的原型对象 在静态方法中,super函数内部的this指向的是子类,而不是子类实例
// 阮一峰 es6文档的例子
class Parent {
static myMethod(msg) { // 代号:1 静态方法, 会被3调用
console.log("static", msg, this);
}
myMethod(msg) { // 代号:2 原型方法,会被4调用
console.log("instance", msg, this);
}
}
class Child extends Parent {
static myMethod(msg) { // 代号3: 静态方法
super.myMethod(msg); // super代表父类,这样写,相当于 Parent.static myMethod.call(Child)
}
myMethod(msg) { // 代号:4 原型方法
super.myMethod(msg); // super代表父类的原型对象,这样写,相当于 Parent.prototype.myMethod.call(this)
}
}
Child.myMethod('类对象-调用静态方法'); // 类,调用静态方法3
var child = new Child();
child.myMethod('实例对象-调用原型方法'); // 实例化对象,调用原型方法4
super中的this指向(总结)
代表父类构造函数使用的 super()
,函数内部的this指向子类实例在普通方法中,代表父类原型对象使用的super,函数内部this指向子类实例 在静态方法中,代表父类使用的super,函数内部this指向子类【就他特殊,单独记忆】
小小提示:使用super的时候,必须显式指定是作为函数还是作为对象使用,否则会报错。
所有《每日一题》的 知识大纲索引脑图 整理在此:https://www.yuque.com/dfe_evernote/interview/everyday
你也可以点击文末的 “阅读原文” 快速跳转
评论