在写React时,咱们常常会写下面这样的组件:javascript
class Checkbox extends React.Component {
constructor(props) {
super(props);
this.state = { isOn: true };
}
// ...
}
复制代码
有几个问题须要值得咱们思考:java
为何咱们要调用 super ? 咱们能不调用 super 吗? 若是咱们必需要调用它,不传 props 会发生什么?它们还有其它参数吗?react
在JavaScript中,super 指向了父级class 的 constructor,(例子中就是 React.Component的原型对象)。 你不能使用 this 在constructor中的 super 调用以前:git
class Checkbox extends React.Component {
constructor(props) {
// 这里不能使用this
super(props);
// 如今这里可使用this
this.state = { isOn: true };
}
// ...
}
复制代码
为何 JavaScript 强制要求咱们调用 super, 在 constructor 中使用 this 前:github
class Person {
constructor(name) {
this.name = name;
}
}
class PolitePerson extends Person {
constructor(name) {
this.greetColleagues(); // 这里不容许咱们使用this,下面解释
super(name);
}
greetColleagues() {
alert('Good morning folks!');
}
}
复制代码
上面的例子假设调用 super 以前容许使用 this, 一段时间后,咱们在 greetColleagues( ) 中添加:ui
greetColleagues() {
alert('Good morning folks!');
alert('My name is ' + this.name + ', nice to meet you!');
}
复制代码
可是咱们忘了,this.greetColleagues( ) 在 super 调用以前,this.name 都没有定义,代码会抛错,像这样的代码可能很难想到何时发生。this
所以,为了不这个陷阱,JavaScript 强制要求在 constructor 中使用 this 以前,必须先调用 super。 这个限制一样也适用在 React Component 中,固然 class fidlds propsal 让咱们也能够经过一些方式来简写,不用这么麻烦写constructor( ):spa
class Checkbox extends React.Component {
state = { isOn: true };
// ...
}
复制代码
为何要传递props?debug
你可能会想,传递 props 给 super 是有必要的,这样它继承的 React.Component 的 constructor 就能初始化this.props:code
// 在React 内部
class Component {
constructor(props) {
this.props = props;
// ...
}
}
复制代码
但它并不单单是为了初始化 this.props, 从它的源码里解释看能够更新Component 状态。实际上即便你调用super() 不传props, 你仍然能访问 this.props 在 render 或者其余方法,这是由于在调用 constructor 后 React 能正确的分配 props 在实例对象上。
// React 内部
const instance = new YourComponent(props);
instance.props = props;
复制代码
所以,即便你忘记传 props 参数给 super( ), React 也会设置 props 能使你访问。可是不是意味着咱们就不须要再传 props 给 super?
并非,由于这样容易由于混乱,尽管你的实例对象执行 constructor 后 React 会分配this.props ,但 this.props 还是 undefined。
// react 内部
class Component {
constructor(props) {
this.props = props;
// ...
}
}
// 你的代码里
class Button extends React.Component {
constructor(props) {
super(); // 咱们不传 props
console.log(props); // {}
console.log(this.props); // undefined
}
// ...
}
复制代码
这会给咱们 debug 带来很大麻烦,React 仍是推荐咱们将props 传递 super:
class Button extends React.Component {
constructor(props) {
super(props); // 咱们传递 props
console.log(props); // {}
console.log(this.props); // {}
}
// ...
}
复制代码
这样就确保 this.props 被设置在执行 constructor。
在 React 16.6 增长了context 在constructor 第二个参数,为何 咱们不写 super(props, context )? 实际上你能够这样写,但实际上 context 用的比较少,因此没有这样传。
最后,随着 class fidlds propsal 这个tc39提案引入,上面的这些问题大部分都不会存在。没有 constructor , 全部的参数都会自动传递过来,就像 state = { } 表达式这样写法,this.props 和 this.context 会自动被引用。