JavaScript中使用Set()添加对象时仍出现重复值是什么原因?
问题描述
在JavaScript中使用Set()实现数据去重、获取唯一值时,返回结果始终存在重复条目。
控制台调试截图:
对应实现代码:
userStories.add({ user_id: storie.user_id, avatar: storie.user.avatar, });
根本原因
Set对重复值的判定遵循SameValueZero算法,和严格相等运算符===的逻辑几乎一致:
- 原始类型(数字、字符串、布尔值等)会直接对比值是否相等
- 对象、数组这类引用类型,只会对比值的内存引用地址,不会深度校验内部属性是否一致
你每次执行add()操作时传入的都是新创建的对象字面量,即使两个对象的user_id、avatar属性值完全相同,它们在内存中也是独立的不同引用,Set会将其判定为两个不重复的值,自然无法实现预期的去重效果。
可行解决方案
- 方案1:改用
Map按唯一标识去重(最推荐,性能最好)
你的场景里user_id本身就是用户的唯一标识,用Map以user_id为键存储数据,相同键的内容会直接覆盖,天然实现按用户维度去重:// 初始化存储结构 const userStories = new Map(); // 遍历数据时执行添加操作 userStories.set(storie.user_id, { user_id: storie.user_id, avatar: storie.user.avatar }); // 最终需要数组结果时,直接取出所有值即可 const uniqueUserList = [...userStories.values()]; - 方案2:序列化后用Set去重(适合简单对象场景)
如果一定要用Set,可以先把对象序列化为字符串存入Set,利用原始类型值的对比规则去重,使用时再反序列化回对象。注意该方法不适用于包含函数、循环引用、undefined值的复杂对象:const tempSet = new Set(); // 添加时序列化 tempSet.add(JSON.stringify({ user_id: storie.user_id, avatar: storie.user.avatar })); // 最终结果反序列化为对象数组 const uniqueUserList = [...tempSet].map(item => JSON.parse(item)); - 方案3:数组方法按唯一字段过滤
如果是对已有的数组做去重,可以直接用filter配合findIndex,按user_id字段过滤重复项:const uniqueUserList = storyList.filter((storie, index, arr) => { return arr.findIndex(item => item.user_id === storie.user_id) === index; });
内容的提问来源于stack exchange,提问作者Pedro Xavier
相关产品推荐
相关产品推荐

