React PropTypes是否不受JavaScript变量提升影响?不同代码顺序为何会导致校验警告差异?
这是个非常典型的容易混淆的点,我来帮你拆解一下你忽略的几个核心关键点:
1. PropTypes 校验的触发时机
React 的 PropTypes 校验(仅在开发环境生效)是在你创建组件元素(也就是写 JSX 或者调用 React.createElement)的那一刻执行的,而不是在组件定义完成时,也不是在渲染阶段。也就是说,当代码执行到 <SayHello firstName={false} /> 这一行时,React 会立刻去读取当前 SayHello 组件上的 propTypes 属性,然后校验传入的 props 是否符合规则。
2. 变量提升≠赋值操作提升
你提到了 JavaScript 的变量提升,但这里要区分「函数声明提升」和「属性赋值」的区别:
function SayHello(...)作为函数声明,确实会被提升到作用域顶部,所以不管你后续怎么给它加属性,函数本身是提前可用的。- 但
SayHello.propTypes = {...}是属性赋值操作,这个操作不会被提升,它会按照代码的书写顺序,在执行到那一行时才会给函数对象加上propTypes属性。
在 Version 2 中,const element = <SayHello firstName={false} /> 这一行先执行了,此时 SayHello 还没有被赋值 propTypes 属性,React 找不到校验规则,自然不会弹出警告;而 Version 1 中,赋值操作在创建元素之前完成,所以校验能正常触发。
3. JSX 编译后的实际执行逻辑
你的 JSX 代码会被 Babel 编译成原生 JavaScript:
// 原JSX const element = <SayHello firstName={false} />; // 编译后等价于 const element = React.createElement(SayHello, { firstName: false }, null);
React.createElement 这个函数在开发环境下,会在内部直接检查传入的组件(这里是 SayHello)是否有 propTypes,并即时做校验。所以赋值顺序直接决定了校验时是否能读取到规则。
补充个小验证:哪怕你在 Version 2 里把 ReactDOM.render 挪到 propTypes 赋值之后,也不会出现警告——因为校验是在创建 element 的时候完成的,后续再给组件加 propTypes 已经晚了。
内容的提问来源于stack exchange,提问作者Praveen

