React箭头函数优化:两类组件写法的差异与浏览器优化等问题探讨
Great question! Let's dig into the nuances here beyond just the obvious "new function created on each render" detail, and cover all your points:
- Child Component Re-Render Behavior: This is the most impactful difference for real-world performance. If
<z>is aPureComponentor a component optimized withReact.memo, the first approach'sonprop is a fixed instance function reference. That means when the parent re-renders, theonprop passed to<z>doesn't change, so the child skips unnecessary re-renders. With the second approach, every render creates a new function reference, which triggers the child to re-render every time—this has a way bigger performance cost than the function creation itself. - Lifecycle & Binding: The
onfunction in the first approach is created once when the component instance initializes, and it's permanently bound to the instance (thanks to the arrow function's lexicalthis). It exists for the entire lifecycle of the component. The second approach's function is created dynamically every timerenderruns, with itsthisbound to the current instance via lexical scoping, but each instance of the function is brand new. - Memory & GC Overhead: While modern browsers handle garbage collection of short-lived functions efficiently, the second approach generates more temporary function objects with each render. This can add small but cumulative GC pressure over time. The first approach only creates one function per component instance, leading to more stable memory usage.
Browser Optimizations
Browser JIT compilers tend to optimize long-lived functions (like the instance-bound function in the first approach) more effectively—they might inline the function or cache its compiled result. Frequent, short-lived functions (the second approach) are less likely to get these optimizations, though this difference is usually minor compared to the child component re-render issue.
Implementation Differences
Looking at Babel-compiled code reveals clear implementation gaps:
- The first pattern (
on = () => true) gets compiled to create the function in the class constructor and assign it to the instance, like this:class MyComponent { constructor() { this.on = () => true; } render() { return <z on={this.on} />; } } - The second pattern creates the arrow function directly inside the
rendermethod, so a new function is instantiated every timerenderis called.
Should Babel Automatically Convert the Second Form to the First?
Short answer: No, because it would break semantic correctness. The second approach might rely on variables scoped to the render method (for example, if you had const currentValue = this.state.input; in render and used () => currentValue as the handler). Converting that to an instance-level function would lose access to the render-scoped variable, since the instance function is created once during initialization, not on each render when the variable's value might change.
Babel can't safely make this transformation automatically—it's up to you as the developer to refactor handlers into instance properties when they don't depend on render-scoped values, to gain the performance benefits.
内容的提问来源于stack exchange,提问作者FabianCook

