JavaScript如何按消息日期排序数组,含lastMessage对象置顶无消息保留原序
问题原因
你原来的代码存在3个核心错误,导致排序结果不符合预期:
- 没有判断其中一个对象不存在
lastMessage的场景,当其中一侧没有该字段时,访问undefined.createdAt会抛出异常,直接打乱排序逻辑 - 排序回调的返回值逻辑不完整,JS的
Array.sort要求回调返回负数/正数/0三种结果,你现有逻辑只返回1或-1,且时间比较规则写反,无法实现「最新消息在前」的倒序要求 - 没有保留无消息好友的原有相对顺序的逻辑,直接排序会打乱这部分元素的原始位置
解决方案
首先给每个元素标记原始索引保证无消息好友的顺序,再分场景处理排序逻辑,代码如下:
// 先给每个元素添加原始索引,用于无消息时的顺序保留 const indexedData = data.map((item, index) => ({ ...item, _originIndex: index })); indexedData.sort((a, b) => { const aHasMsg = !!a.lastMessage; const bHasMsg = !!b.lastMessage; // 两者都有消息:按时间倒序,最新的在前 if (aHasMsg && bHasMsg) { return new Date(b.lastMessage.createdAt).getTime() - new Date(a.lastMessage.createdAt).getTime(); } // a有消息b没有:a排前面 if (aHasMsg && !bHasMsg) { return -1; } // a没消息b有:b排前面 if (!aHasMsg && bHasMsg) { return 1; } // 两者都没消息:按原始索引升序,保留原有相对顺序 return a._originIndex - b._originIndex; }); // 移除添加的临时索引字段,得到最终结果 const sortedData = indexedData.map(item => { const { _originIndex, ...rest } = item; return rest; });
逻辑说明
- 所有带
lastMessage的好友会全部排在无消息好友的前面 - 带消息的好友之间按消息创建时间倒序排列,时间越新排序越靠前
- 无消息的好友完全保留原始数组中的相对顺序,不会被打乱
内容的提问来源于stack exchange,提问作者Sachin Kumar
相关产品推荐
相关产品推荐

