如何在JS的map函数中正确使用...运算符?解析数据流向
咱们一步步拆解你的代码,搞清楚每一步的...在做什么,以及为什么它和手动传递title、items的效果是等价的。
第一步:map函数里的对象解构+Rest运算符
你写的这段代码:
SHOP_DATA.map(({ id, ...otherProps }) => ( ... ))
这里的{ id, ...otherProps }是对象解构结合Rest运算符的用法:
- 从
SHOP_DATA的每一个元素(比如第一个元素是{ id:1, title:'Hats', routeName:'hats', items:[...] })里,先把id单独提出来(用来做React元素的key)。 - 剩下的所有属性——也就是
title、routeName、items——会被自动打包到otherProps这个新对象里。第一个元素对应的otherProps就是:{ title: 'Hats', routeName: 'hats', items: [ { id: 1, name: 'Brown Brim', ... } ] }
第二步:向组件传递props时的Spread运算符
接下来的{...otherProps}是Spread运算符:
它的作用是把otherProps对象里的每一个键值对“展开”,变成组件的单独props。换句话说:
<CollectionPreview key={id} {...otherProps} />
完全等价于手动写:
<CollectionPreview key={id} title={otherProps.title} routeName={otherProps.routeName} items={otherProps.items} />
这里要注意:key是React的特殊属性,不会作为props传递给CollectionPreview组件,组件内部拿不到key对应的id值。
第三步:组件内部的Rest运算符
你在组件里写的:
const CollectionPreview = ({ id, ...otherProps }) => { ... }
这里又是一次对象解构+Rest运算符,但这里的id其实拿不到值——因为上面传递props时并没有把id传进去(只有title、routeName、items)。所以这个id会是undefined,而组件实际收到的title、routeName、items会被重新打包到组件内部的otherProps里。
为什么和手动传递title、items等价?
你提到的另一种写法:
SHOP_DATA.map(({ id, title , items }) => ( <CollectionPreview key={id} title={title} items={items} /> ))
和你的原写法效果等价的核心原因是:
如果你的CollectionPreview组件只用到了title和items这两个属性,那不管是通过{...otherProps}传递所有剩余属性(包括没用到的routeName),还是手动传递title和items,组件内部能拿到的核心业务属性都是一样的。
当然,如果后续组件需要用到routeName,手动传递的写法就会漏掉这个属性,而原写法会自动包含它——这也是...运算符的优势:当数据源的属性增加时,你不需要手动修改传递props的代码,...会自动把新属性同步传递过去。
内容的提问来源于stack exchange,提问作者NyaSol

