super() VS super(props)
一、ES6 类的继承
ES6 中通过 extends 关键字实现类的继承:
class Father {
  constructor(name) {
    this.name = name
  }
  printName() {
    console.log(this.name)
  }
}
class Child extends Father {
  constructor(name, age) {
    super(name)   // super 代表父类的构造函数
    this.age = age
  }
  printAge() {
    console.log(this.age)
  }
}
let tim = new Child('tim', 20)
tim.printName()  // 输出: tim
tim.printAge()   // 输出: 20
上面通过 super 关键字实现调用父类,super 代表父类的构建函数,使用 super(name) 相当于调用 Father.prototype.constructor.call(this,name)
注意:如果子类中不使用 super 关键字会引发报错。因为子类是没有自己的 this 对象,只能继承父类的 this 对象,然后对其进行加工,而 super() 就是将父类中 this 对象继承给子类的,没有 super() 子类就得不到 this 对象。
如果先调用 this 再初始化 super() 同样会报错:
class Child extends Father {
  constructor(name, age) {
    this.age = age
    super(name) // super 代表父类的构造函数
  }
}
所以在子类 constructor 中,必须先用 super 才能引用 this。
二、React 类组件
React 中类组件是基于 ES6 规范实现的,继承 React.Component,因此如果用到 constructor 就必须写 super() 才能初始化 this。
调用 super() 时,一般都需要传入 props 作为参数,如果不传 React 内部也会将其定义在组件实例中:
// React 内部
const instance = new YourComponent(props)
instance.props = props
所以无论有没有 constructor,render 中 this.props 都可以使用,这是 React 自动附带的,可以不写:
class HelloMessage extends React.Component {
  render() {
    return <div>nice to meet you! {this.props.name}</div>
  }
}
但不建议用 super() 代替 super(props),因为 React 会在类组件构造函数生成实例后再给 this.props 赋值,所以不传递 props 在 super 的情况下,调用 this.props 为 undefined,如下情况:
class Button extends React.Component {
  constructor(props) {
    super();                  // 没传入 props
    console.log(props);       // {}
    console.log(this.props);  // undefined
  // ...
}
而传入 props 则能正常访问,确保了 this.props 在构造函数执行完毕之前已被赋值,更符合逻辑,如下:
class Button extends React.Component {
  constructor(props) {
    super(props);             // 传入 props
    console.log(props);       // {}
    console.log(this.props);  // {}
  // ...
}
三、总结
- React 类组件基于 ES6,所以在constructor中必须使用super关键字;
- 调用 super时无论是否传入 props,React 内部都会将porps赋值给组件实例porps属性中;
- 如果只调用了 super(),没传入 props,则调用 this.props 为undefined。