You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数组含目标对象时includes()返回false的问题排查

为什么includes()检查对象数组时返回false?

问题根源

JavaScript中对象属于引用类型,includes()方法使用**严格相等(===)**进行比较。只有当两个对象指向内存中的同一地址时,===才会返回true。你从Firestore获取的badge.data()是每次调用都会生成的新对象,即使它和userData.obtainedBadges里的对象内容完全一致,二者的内存引用也是不同的,所以includes()会返回false。

另外你的代码还有一个隐性问题:querySnapshot.forEach()中使用async回调是无效的——forEach不会等待异步函数执行完成,会导致setObtainableBadges和setUserBadges的状态更新逻辑混乱。

解决方案

1. 用some()替代includes(),基于唯一标识判断

利用对象的唯一属性(比如id)来判断是否存在,避免引用比较的问题:

2. 替换forEach为for...of,正确处理异步逻辑

修改后的完整代码:

const querySnapshot = await getDocs(colRef);

// 用for...of遍历,支持async/await的顺序执行
for (const badgeDoc of querySnapshot.docs) {
  const badgeData = badgeDoc.data();
  console.log(userData.obtainedBadges);
  
  // 通过id判断用户是否已拥有该徽章
  const isBadgeOwned = userData.obtainedBadges.some(ownedBadge => ownedBadge.id === badgeData.id);
  
  if (!isBadgeOwned) {
    console.log(badgeData);
    console.log("not includes");
    setObtainableBadges(prev => [...prev, badgeData]);
  } else {
    console.log("includes");
    setUserBadges(prev => [...prev, badgeData]);
  }
}

说明

  • some()方法会遍历数组,只要有一个元素满足ownedBadge.id === badgeData.id就返回true,通过唯一标识的数值比较,避开了对象引用的问题。
  • for...of循环可以配合async/await使用,确保每个迭代的逻辑执行完成后再处理下一个,避免状态更新的竞态问题。

内容的提问来源于stack exchange,提问作者Jaydendev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 15:00:53