寻找更简洁的声明方式来减少使用扩展运算符的嵌套

Posted

技术标签:

【中文标题】寻找更简洁的声明方式来减少使用扩展运算符的嵌套【英文标题】:Looking for cleaner declarative way to reduce nesting with spread operator 【发布时间】:2020-04-15 16:18:07 【问题描述】:

当只有一个项目发生变化时,我不喜欢使用映射和循环从 javascript 中的旧数组创建新数组。我有一个简单的数组,其中包含如下数据:

const speakerData = [name: 'joe',id: 101,favorite: true,
                     name: 'sam',id: 102,favorite: false,
                     name: 'jon',id: 103,favorite: false]

并且我想将记录 102 更新为收藏为真(切换收藏)。

我有以下有效的代码:

const speakerId = 102;
const newSpeakerData = speakerData.map((rec) => 
  if (rec.id === speakerId) 
    rec.favorite = !rec.favorite;
    return rec;
   else 
    return rec;
  
);

我想要像下面这样的东西,但它显然不起作用。

const speakerRec = speakerData.find(a=>a.id === speakerId);
speakerRec.favorite = !speakerRec.favorite;
const newSpeakerData = [...speakerData,speakerRec]

有没有一条聪明的方法可以让 ES7 实现这一点?

这是答案我正在寻找@adiga 放在下面的 cmets 中。

const speakerId = parseInt(e.target.attributes['data-sessionid'].value);
const index = speakerData.findIndex((a) => a.id === speakerId);
const newSpeakerData = Object.assign([...speakerData], 
  [index]:  ...speakerData[index], favorite: !speakerData[index].favorite 
);

【问题讨论】:

代替find,使用findIndex,例如:const newSpeakerData = [...speakerData]; const index = speakerData.findIndex(a=>a.id === speakerId); newSpeakerData[index] = <immutably update index>; setState(..) 是我遇到问题的部分 @Victor 您是否赞成超过对该问题的反对票,或者是因为(将鼠标悬停在赞成按钮上)“这个问题显示了研究工作;它有用且清晰” ?您的“或者我理解错了?”表明您并没有真正发现它非常清楚。赞成以平衡反对票is highly inappropriate。 "但它显然不起作用" @Pete 什么不起作用?您显示的内容的前两行seem to do exactly what you are asking for。 我正在寻找比使用 find 或 findrec 更丰富的语言解决方案。如果无法使用扩展运算符,我理解这一点,但我已经看到了其他示例,这些示例似乎可以使用类似于我对 [...,newrec] 的建议的语法。感谢重新打开此内容的人和点赞的人。我一直都在投票,我认为您不必有适当的理由。 【参考方案1】:

一种选择是,在映射时,也将favorite: id === speakerId ? !favorite : favorite 放入返回的对象中:

const speakerData = [
    name: 'joe',
    id: 101,
    favorite: true
  ,
  
    name: 'sam',
    id: 102,
    favorite: false
  ,
  
    name: 'jon',
    id: 103,
    favorite: false
  
];
const speakerId = 102;
const mappedData = speakerData.map(( favorite, name, id ) => (
  name,
  id,
  favorite: id === speakerId ? !favorite : favorite
));
console.log(mappedData);

看起来并不那么漂亮,但这是我更喜欢的,我怀疑是否有更好的方法。

或者,如果你真的需要的话,你可以把它压缩到一行上(但你可能不应该,它太难读了):

const mappedData = speakerData.map(( favorite, name, id ) => ( name, id, favorite: id === speakerId ? !favorite : favorite ));

【讨论】:

【参考方案2】:

您几乎需要 map 来保持数组不可变,但您可能会通过使用条件运算符而不是 if/else 语句来获得更简洁的语法:

const speakerId = 102;
const newSpeakerData = speakerData.map((rec) =>
  rec.id === speakerId
    ? ...rec, favorite: !rec.favorite
    : rec
);

(扩展语法的使用也确保不会改变rec 对象)。

如果还是太长或者缩进太多,当然可以写一个辅助函数来代替like使用

const matchSpeakerId = rec => rec.id === 102;
const newSpeakerData = mapWhere(speakerData, matchSpeakerId, rec => (...rec, favorite: !rec.favorite));

【讨论】:

以上是关于寻找更简洁的声明方式来减少使用扩展运算符的嵌套的主要内容,如果未能解决你的问题,请参考以下文章

在类方法与函数中使用扩展运算符

一名Android程序员如何减少代码中该死的-if-else-嵌套,怎么让代码更简洁?

ArkTS概述系列1

JavaScript |扩展运算符更新嵌套值

Sonarqube - 扩展嵌套的三元运算符

React 的状态如何通过使用扩展运算符来保存文件?