React 的 Component 的构造函数究竟是如何工作的?

How does React's Component's constructor really work?

如果有人能解释为什么下面的代码有效,我将不胜感激。

我创建了一个 NumberListBase React 组件。然后创建了另一个,命名为 NumberList 并派生自 NumberListBase。

在这两个组件的构造函数中,我故意在调用 super() 时不将 'props' 参数传递给父 class。

class NumberListBase extends React.Component {
  constructor(props) {
    super();
    Log("NumberListBase.ctor: ", this.props, props);
  }
}
class NumberList extends NumberListBase {
  constructor(props) {
    super();
    Log("NumberList.ctor: ", this.props, props);
  }
  render() {
    const numbers = this.props.numbers;
    const listItems =
          numbers.map((n) => <li key={`${n}`}>{n}</li>);
    return (<ul>{listItems}</ul>);
  }
}

const numbers = [1, 2, 3, 4, 5];

ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

我预计 render() 会失败,因为 this.props 在其中未定义。

我在构造函数中输入的日志消息清楚地表明 'props' 参数和 'this.props' 在 NumberListBase 构造函数中是 'undefined'。

但是,令人惊讶的是,组件正确呈现并显示了数字,这意味着 'props' 以某种方式到达 React.Component,并且 React.Component 可以将其放入 'this.props'!

这是我为这个问题创建的代码笔。

https://codepen.io/mansoor-omrani/pen/oKaMXV

我还创建了一个 jsfiddle 片段来测试构造函数如何在 class 层次结构中工作。

https://jsfiddle.net/omrani/thnj2zu4/11/

我检查了 React.Component 源代码以了解这个 class 是如何定义的。

https://github.com/facebook/react/blob/master/packages/react/src/ReactBaseClasses.js

function Component(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue;
}

React.Component 只是一个简单的函数。我仍然想知道 'this.props' 的设置方式、地点和时间!

当你在没有 props 的情况下调用 super() 时,你仍然可以在渲染和其他方法中访问 this.props,因为 React 在调用你的构造函数后立即在实例上分配 props。

只有当我们需要在构造函数中使用 props 时,我们才将 props 传递给 super 方法。

他们实现此行为的原因尚不清楚,可能是出于将来的兼容性原因,正如 Robin Pokorny 对以下问题的回答。

参考: