展开运算符只是语法糖,高性能与副本保护取决于对象复用、是否被修改及重渲染控制:透传要快需避免新建对象并用React.memo;副本要稳需浅克隆嵌套对象;透传要准则需解构过滤无效props。

用展开运算符透传 props 本身不自动带来“高性能”或“副本保护”,关键在于怎么用。它只是语法糖,真正起作用的是你传递的对象是否被复用、是否被修改、以及是否触发不必要的重渲染。下面从两个核心目标出发,讲清楚怎么做。
透传要快:避免多余对象创建和重渲染
每次写 {...props} 都会生成一个新对象,哪怕 props 没变,也会让子组件收到新引用,可能触发无意义更新(尤其在 React 中)。
- 对纯展示型子组件,优先用
React.memo包裹,让其跳过 props 浅相等时的重渲染 - 不要在 render 内动态构造透传对象,比如:
{...{...props, extra: 'x'}}—— 这嵌套展开会多建一次对象 - 需要加字段时,用解构+显式合并更可控:
{...props, className: `base ${props.className}`},比先 spread 再赋值更轻量
副本要稳:防止原始 props 被意外修改
展开运算符做的是浅拷贝,只复制第一层属性。如果 props 里有对象或数组,内部引用仍指向原数据 —— 子组件若改了 props.user.name,父组件状态就脏了。
- 透传前不需深拷贝,但要明确哪些字段可被子组件安全修改。通常建议:只透传不可变结构(如字符串、数字、布尔值),或确保子组件不直接 mutate 对象
- 若必须透传嵌套对象且需隔离,可在透传前做一层浅克隆:
{...props, user: {...props.user}},仅克隆风险字段 - Vue 中用
v-bind="props"同样是浅拷贝;配合defineProps的只读约束(Vue 3.4+ 支持withDefaults+ 只读校验),能天然防篡改
透传要准:过滤无效 props,避免污染子组件
直接 {...props} 可能把不需要的字段(比如 ref、key、自定义私有属性)也传下去,某些组件会警告甚至报错。
- 用解构排除法提前筛掉:
const { ref, key, ...rest } = props; return; - 在封装组件时,定义明确的接收接口(TypeScript interface 或 Vue 的
defineProps),让透传逻辑与类型契约对齐 - React 中可用
Object.assign({}, props)替代展开,再删键;但语义不如解构清晰,不推荐日常使用
不复杂但容易忽略











