一句话:
includes和indexOf比的是引用不是「长得像」;==还会把[]和false判成相等——这些坑面试和线上 bug 都高频出现。
写在前面
JavaScript 内置方法用起来顺手,但对象相等、数组查找、NaN 判断等细节一旦理解偏了,就会出现「明明数据在数组里却找不到」「条件判断莫名其妙为 true」的问题。本篇聚焦 includes / indexOf、相等运算符、in 与引用类型 四类易错点。
核心内容
1. includes / indexOf:找的是「同一个引用」
Array.prototype.includes() 和 indexOf() 内部使用 严格相等(===) 比较,对对象和数组而言就是 引用是否相同,不会深比较属性。
javascript
const arr = [
{ a: 1, b: { c: 2 } },
{ d: 3, e: { f: 4 } }
]
const item2 = arr[1]
console.log(arr.includes(item2)) // true
console.log(arr.indexOf(item2)) // 1
// 新建一个「内容相同」的对象 —— 找不到
console.log(arr.includes({ d: 3, e: { f: 4 } })) // false
console.log(arr.indexOf({ d: 3, e: { f: 4 } })) // -1
正确用法
- 已知引用:直接用
includes(item)。 - 按属性匹配:用
find/some:
javascript
const target = { d: 3, e: { f: 4 } }
const found = arr.find(item => item.d === target.d)
const exists = arr.some(item => item.d === 3)
2. 对象与 ===:同结构 ≠ 相等
javascript
const obj1 = { a: 1, b: { c: 2 } }
const obj3 = obj1
const b1 = obj1.b
const b2 = obj1.b
console.log(obj1 === obj3) // true,同一引用
console.log(b1 === b2) // true,同一嵌套对象
console.log({ a: 1 } === { a: 1 }) // false,不同引用
只有两个操作数引用 同一个 对象、数组或函数时,=== 才为 true;属性逐项相同也会是 false。
3. NaN 与相等运算符
javascript
NaN === NaN // false
Number.isNaN(NaN) // true,推荐
isNaN('hello') // true,会先转 Number,慎用
Object.is(NaN, NaN) // true
查找数组中的 NaN:
javascript
[1, NaN, 3].includes(NaN) // true(ES2016 对 NaN 特殊处理)
[1, NaN, 3].indexOf(NaN) // -1(indexOf 仍按 ===,NaN !== NaN)
4. == 隐式转换的经典陷阱
== 会在比较前做类型转换,容易出反直觉结果:
javascript
[] == false // true:[] → '' → 0,false → 0
{} == false // false:{} → NaN,false → 0,NaN 与任何值都不等
null == undefined // true
0 == '' // true
空数组在布尔上下文为 truthy,但与 false 用 == 比较时会走 Number 转换链。
实践建议:业务代码统一用 === / !==;需要区分 null 与 undefined 时再用 == null 这一特例。
5. in 运算符:查属性键而非数组「值」
javascript
const obj1 = { a: 1, b: { c: 2 } }
console.log('b' in obj1) // true
const arr = [10, 20]
console.log(0 in arr) // true,0 是索引键
console.log(10 in arr) // false,10 不是键
踩坑
- 用 indexOf 判断对象是否在数组:内容相同的新对象永远返回 -1。
- 用 indexOf 找 NaN:应改用
includes(NaN)或find(Number.isNaN)。 - 深比较手写 JSON.stringify:键序、undefined、循环引用都会坑;需要时用 lodash
isEqual或 structuredClone 前先明确需求。 - == 与 falsy 混用:
if (!arr.length)比arr == false清晰得多。
小结
- 对象/数组查找:
includes/indexOf比引用;按值匹配用find/some。 - 相等:对象用
===看引用;NaN 用Number.isNaN或includes。 - 避免
==隐式转换;空数组[] == false为 true 是经典面试题。


全部评论(1)