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

use*_*067 9 javascript es6-class

我一直在React js编码.我已经读过在ES6课程中访问'this'我们需要先调用super(道具),我想知道为什么这是.答案我发现主要是谈论Javascript无法知道'这'是什么,除非超类叫做.我想知道这是什么意思,因为在构造函数之外,'this'被识别,我们每次都不调用super(props).

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

Lyu*_*mir 11

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


简短的故事:不允许调用之前访问this子类super(),因为在 ES6 中this是在基类中生成的,因此super()需要对其进行初始化。

更多信息请参考15.6.2 分配和初始化实例1。作者是为数不多的详细解释这一点的人之一。

以下是上述书籍1 中的相关示例。

在引擎盖下,它大致如下所示。

// 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;
}
Run Code Online (Sandbox Code Playgroud)


小智 7

构造函数默认返回'this'.根据oops概念,子类总是通过super()调用从父类继承'this'对象.因此,如果我们尝试在没有超级调用的子类中使用它,它将引发错误.如果我们从子类返回除"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 
Run Code Online (Sandbox Code Playgroud)

例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}
Run Code Online (Sandbox Code Playgroud)

例3

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

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

const instanceB = new B();
console.log(instanceB) // B {a: 0}
Run Code Online (Sandbox Code Playgroud)


ant*_*ono 6

构造函数方法是一种特殊的方法,用于创建和初始化用类创建的对象。一个类中只能有一个名为“构造函数”的特殊方法。如果类包含不止一次的构造函数方法,则将抛出 SyntaxError。构造函数可以使用 super 关键字来调用父类的构造函数。

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

这意味着如果你有class MyComponent extends React.Component你总是需要super()打电话来定义它。

如果未指定构造函数方法,则使用默认构造函数。

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

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

  • 我觉得这两个引用根本没有回答问题,你的评论只是重复了事实而不解释。 (24认同)
  • 当你不写时,为什么对“super()”的调用不是隐含的?有充分的理由吗? (5认同)
  • 好。那我补充几句吧。在子类开始配置`this`之前,应该首先调用超类的构造函数以完成`this`的配置。否则超类构造函数可能会被子类修改“this”。超类不应该了解子类。这就是为什么构造函数中的“super()”调用应该在访问“this”之前。 (2认同)