在 React 的源码中,闭包被广泛使用,主要是因为闭包可以帮助 React 实现一系列关键的功能,如组件的生命周期管理、Hooks 的实现、以及调度机制等。以下是 React 源码中关于闭包的一些典型应用:

1. 组件的生命周期管理

React 组件的生命周期方法(如 componentDidMountcomponentDidUpdatecomponentWillUnmount)在内部实现时,经常利用闭包来保存状态。

class MyComponent extends React.Component {
  componentDidMount() {
    this._timeoutID = setTimeout(() => {
      console.log('Component did mount');
    }, 1000);
  }
 
  componentWillUnmount() {
    clearTimeout(this._timeoutID);
  }
}

在这个例子中,componentDidMount 方法中的 this._timeoutID 形成了一个闭包,它在 componentWillUnmount 中被访问和清除。

2. Hooks 的实现

React Hooks 的实现依赖于闭包来保存状态。每个 Hook 都是一个函数,它返回一个闭包,这个闭包可以访问和修改 Hook 的状态。

function useState(initialState) {
  const [state, setState] = React.useReducer(
    (s, a) => typeof a === 'function' ? a(s) : a,
    initialState
  );
  return [state, setState];
}

在这个例子中,useState Hook 返回一个闭包,这个闭包可以访问和修改状态。

3. 调度机制

React 的调度机制(如 requestAnimationFramesetTimeout)在内部实现时,经常利用闭包来保存状态和调度信息。

function scheduleWork(callback, priority) {
  const timeout = priority === ImmediatePriority ? 0 : 100;
  setTimeout(() => {
    if (callback) {
      callback();
    }
  }, timeout);
}

在这个例子中,setTimeout 函数中的 callback 形成了一个闭包,它在定时器到期时被调用。

4. 错误边界

React 的错误边界(如 componentDidCatch)在内部实现时,经常利用闭包来保存错误信息。

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null, errorInfo: null };
  }
 
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
 
  componentDidCatch(error, errorInfo) {
    this.setState({ error: error, errorInfo: errorInfo });
  }
 
  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
 
    return this.props.children;
  }
}

在这个例子中,componentDidCatch 方法中的 this.setState 形成了一个闭包,它在错误发生时被调用。

总结

闭包在 React 源码中有着广泛的应用,它可以帮助 React 实现一系列关键的功能。通过理解闭包在 React 源码中的应用,我们可以更好地理解 React 的工作原理,以及如何编写高效的 React 应用。