Array.prototype.includes 是 JavaScript 数组原型上的一个方法,用于判断当前数组是否包含某个指定值。它的返回值是一个布尔值:如果找到目标值就返回 true,没有找到就返回 false。相比过去常见的 indexOf 判断方式,includes 的语义更加直接,代码读起来更接近自然语言表达,特别适合用于权限判断、状态判断、标签判断等“是否包含”的场景。

includes 方法的基本语义与语法结构
Array.prototype.includes 的核心作用非常明确:判断数组中是否存在某个值。调用这个方法时,数组本身是调用者,传入的第一个参数是要查找的目标值。方法执行后不会修改原数组,只会返回一个布尔结果。这种设计使它非常适合用于条件判断,不需要再额外处理索引值,也不需要手动比较返回值是否等于某个特殊数字。
它的语法可以写成 arr.includes(searchElement, fromIndex)。其中,searchElement 是必填参数,表示要查找的值;fromIndex 是可选参数,表示从数组的哪个位置开始查找。如果没有提供第二个参数,默认从索引 0 开始,也就是从数组头部一直查找到尾部。如果 fromIndex 大于或等于数组长度,方法会直接返回 false,因为此时已经没有可查找的范围。
当 fromIndex 是负数时,它会从数组末尾向前计算起始位置。例如,传入 -1 表示从最后一个元素开始查找,传入 -2 表示从倒数第二个元素开始查找。需要注意的是,负数参数改变的是查找起点,查找方向仍然是从该起点向数组末尾进行。理解这一点,可以避免误以为负数索引会反向遍历数组。
const fruits = ['apple', 'banana', 'cherry'];
// 查找普通元素
console.log(fruits.includes('banana')); // true
console.log(fruits.includes('grape')); // false
// fromIndex 表示开始查找的位置
console.log(fruits.includes('apple', 1)); // false
console.log(fruits.includes('banana', 1)); // true
// 负数 fromIndex 从数组末尾向前计算
console.log(fruits.includes('cherry', -1)); // true
console.log(fruits.includes('apple', -2)); // false
常见使用场景与容易忽略的边界情况
在实际开发中,includes 最常见的用途是判断某个值是否存在于一组候选值中。例如,判断用户角色是否包含管理员,判断当前页面状态是否属于可编辑状态,或者判断请求返回的标签列表中是否包含某个关键词。由于它返回布尔值,直接放在 if 条件中非常自然,不需要像过去那样写 indexOf 后再与 -1 比较。
另一个常见场景是利用第二个参数控制查找范围。比如数组中可能存在重复值,而我们只关心某个位置之后是否仍然存在目标值,就可以通过 fromIndex 跳过前面的元素。这个能力在分页数据检查、序列校验、重复项判断等场景中很有用。虽然它不会返回具体位置,但对于只关心“有没有”的需求来说,已经足够清晰。
不过,includes 也有一些需要特别注意的边界情况。首先是稀疏数组。如果数组中存在空位,includes 会把这些空位当作 undefined 来处理。因此,当数组中确实存在空位时,查找 undefined 可能返回 true。其次是对象类型的比较。includes 判断对象时比较的是引用地址,而不是对象内部的属性内容。两个结构相同的对象,如果不是同一个引用,也会被认为不相等。
const permissions = ['read', 'write'];
if (permissions.includes('write')) {
console.log('允许编辑');
}
const statuses = ['pending', 'reviewing', 'published'];
console.log(statuses.includes('reviewing')); // true
console.log(statuses.includes('archived')); // false
// 从指定位置开始查找
const ids = [101, 102, 103, 102];
console.log(ids.includes(102, 2)); // true
console.log(ids.includes(101, 2)); // false
// 稀疏数组中的空位会被当作 undefined 处理
const sparseList = ['a', , 'c'];
console.log(sparseList.includes(undefined)); // true
console.log(sparseList.includes('b')); // false
// 对象比较的是引用地址,而不是对象内容
const config = { mode: 'dark' };
const list = [config];
console.log(list.includes(config)); // true
console.log(list.includes({ mode: 'dark' })); // false
includes 与 indexOf 的差异以及兼容思路
在 includes 出现之前,很多开发者会使用 indexOf 来判断数组是否包含某个值。典型写法是先获取索引,再判断索引是否不等于 -1。这种写法虽然可以完成任务,但语义上更像是在询问“这个值在哪里”,而不是“这个值是否存在”。当业务只关心是否存在时,includes 显然更贴近意图。
两者更重要的差异体现在对特殊值的处理上。includes 使用 SameValueZero 算法进行比较,这种算法在大多数情况下与严格相等类似,但它认为两个 NaN 是相等的。而 indexOf 的判断思路更接近严格相等,由于 NaN 不等于自身,所以 indexOf(NaN) 通常无法正确找到 NaN。这一点在处理数值校验、异常值判断时尤其重要。
| 对比项 | includes 方法 | indexOf 方法 |
|---|---|---|
| 返回值类型 | 布尔值,直接表达是否包含 | 数字,返回索引位置,未找到时返回 -1 |
| 对 NaN 的处理 | 可以正确识别 NaN | 无法正确识别 NaN |
| 代码语义 | 更适合表达“是否存在” | 更适合表达“位置在哪里” |
| 比较方式 | 使用 SameValueZero 算法 | 更接近严格相等判断 |
const values = [10, NaN, 20];
// includes 可以识别 NaN
console.log(values.includes(NaN)); // true
// indexOf 对 NaN 不友好
console.log(values.indexOf(NaN)); // -1
// 写法可读性对比
if (values.includes(10)) {
console.log('包含 10');
}
if (values.indexOf(10) !== -1) {
console.log('包含 10');
}
从使用建议来看,如果只需要判断数组是否包含某个值,优先使用 includes 通常会让代码更简洁。如果除了判断是否存在,还需要拿到目标值第一次出现的位置,那么 indexOf 仍然有它的价值。换句话说,两者并不是简单替代关系,而是分别服务于不同的查询目的。
另外,在当下大多数 JavaScript 运行环境中,Array.prototype.includes 已经可以被直接使用。但如果项目需要兼容一些较旧的浏览器环境,可以通过 polyfill 手动补齐这个方法。下面的示例实现了一个基础兼容方案,重点模拟了起始索引计算以及对 NaN 的判断逻辑。
if (!Array.prototype.includes) {
Object.defineProperty(Array.prototype, 'includes', {
value: function (searchElement, fromIndex) {
if (this == null) {
throw new TypeError('this is null or not defined');
}
var target = Object(this);
var length = target.length >>> 0;
if (length === 0) {
return false;
}
var start = fromIndex | 0;
var index = start >= 0 ? start : Math.max(length - Math.abs(start), 0);
// SameValueZero:普通严格相等,并认为两个 NaN 相等
function sameValueZero(x, y) {
return x === y || (x !== x && y !== y);
}
while (index < length) {
if (sameValueZero(target[index], searchElement)) {
return true;
}
index++;
}
return false;
}
});
}
总体而言,Array.prototype.includes 是一个语义清晰、使用频率很高的数组方法。它的优势在于直接返回布尔结果,并且能够正确处理 NaN 这类特殊值。在使用时,只要理解 fromIndex 的起始位置规则、稀疏数组空位的处理方式,以及对象比较基于引用地址这几个关键点,就能在大多数数组包含判断场景中安全、自然地使用它。
Array.prototype.includesJavaScript数组方法数组查找ES6新特性includes用法修改时间:2026-06-29 02:36:17