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

时间:2017-04-21 09:59:06

标签: javascript es6-class

我一直在使用React js进行编码。我已经在ES6课程中读到了这个'这个'我们需要先调用super(道具),我想知道为什么会这样。答案我发现主要是谈论Javascript无法知道'这个'除非调用超类。我想知道这意味着什么,因为在构造函数之外,'这个'被认可,我们不会每次都打电话给超级(道具)。

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

3 个答案:

答案 0 :(得分: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 

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

答案 1 :(得分:5)

  

构造函数方法是一种用于创建和初始化使用类创建的对象的特殊方法。在类中只能有一个名为“constructor”的特殊方法。如果类包含多个构造函数方法,则将抛出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之前。

答案 2 :(得分:1)

不幸的是,这确实很复杂。


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

有关更多信息,请参阅15.6.2 Allocating and initializing instances 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;
}