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
。