super 关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
1、super当做函数使用
super 作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次 super() 函数。注意:作为函数时,super() 只能用在子类的构造函数之中,用在其他地方就会报错。
- class A {}
- class B extends A {
- constructor() {
- super();
- }
- }
super 作为函数调用时,内部的 this 指的是子类实例
- class A {
- constructor() {
- this.show();
- }
- }
- class B extends A {
- constructor() {
- super();
- }
- show(){
- console.log(‘实例‘);
- }
- static show(){
- console.log(‘子类‘);
- }
- }
- new B() //输出 ‘实例‘ ,new B 时触发了 B 的构造函数,所以触发了 super 方法,即触发了父类 A 的构造函数,此时的 this.show 的 this 指的是子类
2、super 作为对象使用
super 作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
2.1、super在普通方法中(即非静态方法)及此时的 this 关键字指向
- class A {
- p() {
- return 2;
- }
- }
- class B extends A {
- constructor() {
- super();
- console.log(super.p()); // 2 此时的super指向父类原型对象,即 A.prototype
- }
- }
- let b = new B(); //2
由于在普通方法中的 super 指向父类的原型对象,所以如果父类上的方法或属性是定义在实例上的,就无法通过 super 调用的。如下所示:
- class A {
- constructor() { //在构造函数上定义的属性和方法相当于定义在父类实例上的,而不是原型对象上
- this.p = 2;
- }
- }
- class B extends A {
- get m() {
- return super.p;
- }
- }
- let b = new B();
- console.log(b.m) // undefined
在子类普通方法中通过 super 调用父类的方法时,方法内部的 this 指向的是当前的子类实例。
- class A {
- constructor() {
- this.x = 1;
- }
- print() {
- console.log(this.x);
- }
- }
- class B extends A {
- constructor() {
- super();
- this.x = 2;
- super.y = 123; //如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
- }
- m() {
- super.print();
- }
- }
- let b = new B();
- b.m() // 2
- console.log(b.y); //123
2.2、super在静态方法中及此时的 this 关键字指向
super作为对象,用在静态方法之中,这时 super 将直接指向父类,而不是父类的原型对象。
- class Parent {
- static myMethod(msg) {
- console.log(‘static‘, msg);
- }
- myMethod(msg) {
- console.log(‘instance‘, msg);
- }
- }
- class Child extends Parent {
- static myMethod(msg) {
- super.myMethod(msg);
- }
- myMethod(msg) {
- super.myMethod(msg);
- }
- }
- Child.myMethod(1); // static 1
- var child = new Child();
- child.myMethod(2); // instance 2
在子类的静态方法中通过 super 调用父类的方法时,方法内部的 this 指向当前的子类,而不是子类的实例。
- class A {
- constructor() {
- this.x = 1;
- }
- static print() {
- console.log(this.x);
- }
- }
- class B extends A {
- constructor() {
- super();
- this.x = 2;
- }
- static m() {
- super.print();
- }
- }
- B.x = 3;
- B.m() // 3