Skip to main content

super() VS super(props)

一、ES6 类的继承

点击查看 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

所以无论有没有 constructorrenderthis.props 都可以使用,这是 React 自动附带的,可以不写:

class HelloMessage extends React.Component {
render() {
return <div>nice to meet you! {this.props.name}</div>
}
}

但不建议用 super() 代替 super(props),因为 React 会在类组件构造函数生成实例后再给 this.props 赋值,所以不传递 propssuper 的情况下,调用 this.propsundefined,如下情况:

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.propsundefined