简体   繁体   中英

Why isn't this allowed before super()

I have been coding in React js. I have read that in ES6 classes to access 'this' we need to first call super(props) and I would like to know why this is.Answers I have found mainly talk about Javascript being unable to know what 'this' is unless superclass is called. I would like to know what that means because outside the constructor, 'this' is recognized and we don't call super(props) each time.

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { /* initial state */ };
  }
}

Constructor function will return 'this' by default. According to oops concept child class always inherit 'this' object from parent class by super() call. so if we try to use this in child class without super call it will throw an error. If we return anything except 'this' from child class then super() call is not necessary. I have explained by some simple examples.

example 1

class A {
  constructor() {
    this.a = 0;
  }
}

class B extends A {
    constructor() {
        console.log(this);
    }
}
const instanceA = new A();
console.log(instanceA) // A {a: 0}
const instanceB = new B();
console.log(instanceB) // Error: Must call super constructor in derived class before 
accessing 'this' or returning from derived constructor 

example 2

class A {
  constructor() {
    this.a = 0;
  }
}

class B extends A {
    constructor() {
      return {b: 3}
    }
}
const instanceA = new A();
console.log(instanceA) // A {a: 0}
const instanceB = new B();
console.log(instanceB) // Object {b: 3}

example 3

class A {
  constructor() {
    this.a = 0;
  }
}

class B extends A {
    constructor() {
      super()
    }
}

const instanceB = new B();
console.log(instanceB) // B {a: 0}

The constructor method is a special method for creating and initializing an object created with a class. There can only be one special method with the name "constructor" in a class. A SyntaxError will be thrown if the class contains more than one occurrence of a constructor method. A constructor can use the super keyword to call the constructor of a parent class.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

It means if you have class MyComponent extends React.Component you always need super() call in order to make this defined.

If you don't specify a constructor method, a default constructor is used.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/constructor#Default_constructors

Constructor of superclass should be called before this in order to finish configuration of this before subclass started configuration of this . Otherwise superclass constructor could get this modified by subclass. Superclass should not know something about subclasses. That is why super() call in constructor should be before access to this .

This is really complicated, unfortunately.


The short story: access of this in a subclass before super() call is not allowed, because in ES6 this is being born in the base class , therefore super() is needed to initialize it.

For more information, refer to 15.6.2 Allocating and initializing instances 1 . The author is one of the few people that explains this in detail.

Here is a relevant sample from the book 1 above.

Under the hood, it roughly looks as follows.

// Base class: this is where the instance is allocated
function Person(name) {
    // Performed before entering this constructor:
    this = Object.create(new.target.prototype);

    this.name = name;
}
···

function Employee(name, title) {
    // Performed before entering this constructor:
    this = uninitialized;

    this = Reflect.construct(Person, [name], new.target); // (A)
        // super(name);

    this.title = title;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM