
无法规避。Array.prototype.indexOf() 在设计上就无法正确识别 NaN,这是它的固有行为,不是使用方式问题。
为什么 indexOf 对 NaN 总是返回 -1
因为 indexOf 内部使用严格相等(===)判断,而 JavaScript 规定 NaN === NaN 为 false。即使数组里明确存着 NaN,indexOf 也找不到它:
-
[NaN].indexOf(NaN)→ -1 -
[1, NaN, 3].indexOf(NaN)→ -1
includes 能处理 NaN 是因为它用的是 SameValueZero 算法
SameValueZero 把两个 NaN 视为相等,所以:
-
[NaN].includes(NaN)→ true -
[1, NaN, 3].includes(NaN)→ true
这不是 includes “更聪明”,而是规范层面的算法差异——indexOf 没有、也不能通过参数或技巧绕过这个限制。
如果必须用 indexOf 场景,只能手动补救
仅当无法使用 includes(如需兼容极旧环境且必须检测 NaN)时,可加一层判断:
- 先用
isNaN()单独检查目标值是否为 NaN - 若是,再遍历数组用
Number.isNaN(item)逐个比对 - 否则才调用
indexOf()
例如:
function safeIndexOf(arr, target) {<br> if (Number.isNaN(target)) {<br> for (let i = 0; i < arr.length; i++) {<br> if (Number.isNaN(arr[i])) return i;<br> }<br> return -1;<br> }<br> return arr.indexOf(target);<br>}
实际开发中建议直接换用 includes
ES6+ 环境下,检测“是否存在”应优先用 includes:
- 语义清晰:
arr.includes(NaN)直观表达意图 - 无需额外逻辑:自动兼容 NaN、稀疏数组中的 empty slot
- 性能无实质损失:底层虽基于 indexOf,但多一次比较的开销可忽略
只有当你需要获取匹配项的**具体位置**(比如后续要 splice 或替换),才必须用 indexOf ——但此时若涉及 NaN,就说明数据建模可能需要调整,比如避免在数组中直接存 NaN,改用 null 或特殊标记值。

















