Reprinted from ruan Yifeng’s introduction to ECMAScript 6 (ES6) standards, 3rd edition

The super keyword can be used as either a function or an object. In both cases, it’s used quite differently.

Call as a function

When called as a function, super represents the constructor of the parent class. ES6 requires that the constructor of a subclass must execute the super function once.

class A {}
class B extends A {
  constructor() {
    super();
  }
}
Copy the code

In the code above, super() in the constructor of subclass B stands for calling the constructor of the parent class. This is necessary, otherwise the JavaScript engine will report an error.

Note that super although represents the parent class constructor, but returns the instance of the subclass B, namely the inside of the super this refers to the instance of B so super () is equivalent to Amy polumbo rototype here. The constructor. Call (this).

class A {
  constructor() {
    console.log(new.target.name); }}class B extends A {
  constructor() {
    super();
  }
}
new A() // A
new B() // B
Copy the code

In the above code, new.target points to the function currently executing. As you can see, when super() executes, it points to the constructor of subclass B, not the constructor of superclass A. That is, the this inside super() refers to B.

When used as a function, super() can only be used in the constructor of a subclass, otherwise an error will be reported.

class A {}
class B extends A {
  m() {
    super(a);/ / an error}}Copy the code

In the code above, using super() in the m method of class B causes a syntax error.

As an object

When super is an object, in a normal method, it points to the prototype object of the parent class; In static methods, point to the parent class.

class A {
  p() {
    return 2; }}class B extends A {
  constructor() {
    super(a);console.log(super.p()); / / 2}}let b = new B();
Copy the code

In the code above, super.p() in subclass B uses super as an object. In this case, super refers to a.prototype in normal methods, so super.p() equals a.prototype.p ().

It is important to note that since super refers to the parent’s prototype object, methods or properties defined on the parent instance cannot be called by super.

class A {
  constructor() {
    this.p = 2; }}class B extends A {
  get m() {
    return super.p; }}let b = new B();
b.m // undefined
Copy the code

In the code above, p is an attribute of an instance of superclass A. super.p does not refer to it.

Super can be fetched if the property is defined on a stereotype object of the parent class.

class A {}
A.prototype.x = 2;
class B extends A {
  constructor() {
    super(a);console.log(super.x) / / 2}}let b = new B();
Copy the code

In the code above, the attribute x is defined above a.protoType, so super.x can take its value.

ES6 states that when a method of a parent class is called through super in a subclass normal method, this inside the method refers to the current subclass instance.

class A {
  constructor() {
    this.x = 1;
  }
  print() {
    console.log(this.x); }}class B extends A {
  constructor() {
    super(a);this.x = 2;
  }
  m() {
    super.print(); }}let b = new B();
b.m() / / 2
Copy the code

In the code above, super.print() calls a.prototype.print (), but the this inside a.prototype.print () points to an instance of subclass B, resulting in 2 instead of 1. That is, super.print.call(this) is actually executed.

Since this refers to the subclass instance, if you assign a value to a property via super, which is this, the assigned property becomes the property of the subclass instance.

class A {
  constructor() {
    this.x = 1; }}class B extends A {
  constructor() {
    super(a);this.x = 2;
    super.x = 3;
    console.log(super.x); // undefined
    console.log(this.x); / / 3}}let b = new B();
Copy the code

In the code above, assigning super.x to 3 is the same as assigning this.x to 3. When super.x is read, a.prototype. x is read, so return undefined.

If super is used as an object in a static method, then super refers to the parent class, not the parent class’s prototype object.

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
Copy the code

In the code above, super refers to the parent class in static methods and to the parent class’s prototype object in normal methods.

Also, when a method of a parent class is called through super in a static method of a subclass, the this inside the method refers to the current subclass, not the instance of the subclass.

class A {
  constructor() {
    this.x = 1;
  }
  static print() {
    console.log(this.x); }}class B extends A {
  constructor() {
    super(a);this.x = 2;
  }
  static m() {
    super.print();
  }
}
B.x = 3;
B.m() / / 3
Copy the code

In the code above, in the static method B.m, super.print points to the static method of the parent class. This in this method refers to B, not an instance of B.

Note that when you use super, you must explicitly specify whether to use it as a function or as an object, otherwise an error will be reported.

class A {}
class B extends A {
  constructor() {
    super(a);console.log(super); / / an error}}Copy the code

In the code above, the super in console.log(super) is not clear if it is used as a function or as an object, so the JavaScript engine will report an error when parsing the code. At this point, if the data type of super is clearly stated, no errors will be reported.

class A {}
class B extends A {
  constructor() {
    super(a);console.log(super.valueOf() instanceof B); // true}}let b = new B();
Copy the code

In the code above, super.valueof () indicates that super is an object, so no error is reported. Also, since super makes this refer to an instance of B, super.valueof () returns an instance of B.

Finally, since objects always inherit from other objects, the super keyword can be used in any object.

var obj = {
  toString() {
    return "MyObject: " + super.toString(); }}; obj.toString();// MyObject: [object Object]
Copy the code