为什么在 super() 之前不允许这样做

Why isn't this allowed before super()

我一直在用 React js 编写代码。我读过在 ES6 类 中访问 'this' 我们需要先调用 super(props) 我想知道为什么这个 is.Answers 我发现主要是谈论 Javascript 除非调用超类,否则无法知道 'this' 是什么。我想知道这意味着什么,因为在构造函数之外,'this' 被识别,我们不会每次都调用 super(props)。

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

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

这意味着如果你有 class MyComponent extends React.Component 你总是需要 super() 调用才能定义它。

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

超类的构造函数应该在 this 之前调用,以便在子类开始配置 this 之前完成 this 的配置。否则超类构造函数可能会被子类修改 this 。超类不应该对子类有所了解。这就是为什么 super() 调用构造函数应该在访问 this.

之前

构造函数默认会return 'this'。根据 oops 概念,子 class 总是通过 super() 调用从父 class 继承 'this' 对象。因此,如果我们尝试在不调用 super 的情况下在子 class 中使用它,它将引发错误。 如果我们 return 除了来自子 class 的 'this' 之外的任何东西,那么 super() 调用是不必要的。 我已经通过一些简单的例子来解释了。

示例 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 

示例 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}

示例 3

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

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

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

不幸的是,这真的很复杂。


短篇小说:super() 调用之前的子 class 中访问 this 是不允许的,因为在 ES6 中 this出生于基地class,因此需要super()初始化

更多信息,请参阅15.6.2 Allocating and initializing instances1。作者是为数不多的对此进行详细解释的人之一。

这是上面的书1中的相关示例。

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;
}