includes不适合直接去重,因其基于samevaluezero比较:虽能正确识别nan,但对对象等引用类型只比地址,且将0与-0视为相等,无法满足业务语义下的安全去重需求。

includes 本身不用于去重,它是判断元素是否存在的方法;但可以配合 filter 和 indexOf(或 lastIndexOf)来实现“基于 includes 的去重逻辑”,不过要注意它**不是最安全或最高效的方式**——尤其在处理 NaN、对象、或存在 undefined/null 等特殊值时容易出错。
为什么 includes 不适合直接做去重?
includes 使用的是 SameValueZero 比较算法:
✅ 能正确识别 NaN([NaN].includes(NaN) === true)
❌ 但对对象、函数、Symbol 等引用类型,只比较引用地址,不是内容相等
❌ 对于 0 和 -0,includes 认为它们相等(SameValueZero 规则),有时这不符合“业务意义下的去重”需求
用 includes 实现基础去重(仅限原始值且无 NaN 风险场景)
如果确定数组只含字符串、数字(不含 -0)、布尔值、null、undefined,且不需要深比较,可这样写:
const unique = arr => arr.filter((item, index) => arr.indexOf(item) === index);
或者用 includes 模拟(语义更直白,但性能略差):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const unique = arr => arr.filter((item, index) => arr.slice(0, index).includes(item) === false);
- 每次检查当前元素是否在前面子数组中已出现过
- 避免了
indexOf对NaN的误判(NaN === NaN是 false,但includes能识别) - 时间复杂度是 O(n²),大数据量时不推荐
真正安全的去重方式(推荐替代方案)
根据数据类型选择更健壮的方法:
-
原始值 + NaN 支持:用
Array.from(new Set(arr))—— Set 内部也用 SameValueZero,能正确处理NaN,简洁且高效 -
对象数组按某字段去重:用
Map或filter + findIndex,例如:
arr.filter((item, i) => arr.findIndex(v => v.id === item.id) === i) -
深比较去重(如嵌套对象):需序列化(慎用 JSON.stringify,会忽略函数、undefined、Symbol)或使用 Lodash 的
uniqWith(eq) - 需要区分 -0 和 0:得手写比较逻辑,因为 SameValueZero 把它们当相等,而实际业务可能要保留两者
小结:includes 可以“用”,但别迷信它“安全”
它只是提供了一种可读性尚可的去重写法,本质仍是浅比较、O(n²)、无法处理引用类型唯一性。生产环境优先选 Set,复杂场景用 Map 或专用工具函数。安全 ≠ 写法简单,而是匹配数据特征和业务语义。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










