JavaScript includes() 方法(千字长文)

JavaScript includes() 方法:高效判断数组中是否存在元素

在日常开发中,我们经常需要判断一个值是否存在于某个数据集合中。比如,检查用户是否有权限访问某个功能、验证输入的选项是否在允许范围内,或者判断一个商品是否在购物车里。这些场景都离不开一个基础但非常实用的能力——“是否存在”。

JavaScript 为我们提供了 includes() 方法,它就是专门用来解决这类问题的利器。相比传统的 indexOf() 方法,includes() 更直观、更语义化,而且支持对 NaN 的正确判断。今天我们就来深入聊聊这个看似简单却功能强大的方法。


什么是 JavaScript includes() 方法?

includes() 是数组原型上的一个方法,用于判断数组中是否包含某个指定的元素。它返回一个布尔值:true 表示存在,false 表示不存在。

它的语法非常简洁:

array.includes(searchElement, fromIndex)
  • searchElement:要搜索的元素(必须)
  • fromIndex:可选参数,表示从哪个索引位置开始搜索,默认为 0

💡 小贴士:includes() 会使用严格相等(===)进行比较,这意味着类型也必须一致,比如 '5'5 是不同的。


基本用法:快速判断元素是否存在

让我们从最基础的使用开始。假设你有一个用户角色列表,需要判断某个角色是否被允许访问系统。

const roles = ['admin', 'editor', 'viewer'];

// 判断是否存在 'editor' 角色
const hasEditor = roles.includes('editor');

console.log(hasEditor); // true

在这个例子中,includes() 直接返回 true,说明 'editor' 确实在数组中。这比手动循环或使用 indexOf() 判断是否大于等于 0 更简洁清晰。

⚠️ 注意:includes() 不会修改原数组,它是纯函数,安全无副作用。


处理不同数据类型:字符串、数字、布尔值

includes() 支持多种数据类型,包括字符串、数字、布尔值、对象引用等。我们来分别看看:

字符串数组

const fruits = ['apple', 'banana', 'orange'];

console.log(fruits.includes('banana'));     // true
console.log(fruits.includes('grape'));      // false

数字数组

const scores = [85, 92, 78, 96];

console.log(scores.includes(92));   // true
console.log(scores.includes(60));   // false

布尔值数组

const flags = [true, false, true];

console.log(flags.includes(false)); // true
console.log(flags.includes(null));  // false

✅ 关键点:includes()NaN 的处理是特殊的。它能正确识别 NaN,而 indexOf() 不能。

const data = [1, 2, NaN, 4];

console.log(data.includes(NaN));     // true
console.log(data.indexOf(NaN));      // -1 (错误!)

这说明 includes() 在处理 NaN 时更可靠,是我们在处理含 NaN 数据时的首选方法。


使用 fromIndex 参数:从指定位置开始搜索

fromIndex 参数让我们可以控制搜索的起始位置,非常实用。比如,你只想检查数组后半部分是否包含某个值。

const numbers = [1, 2, 3, 4, 5, 3, 6];

// 从索引 4 开始查找 3
console.log(numbers.includes(3, 4)); // true(因为索引 5 的值是 3)

// 从索引 5 开始查找 3
console.log(numbers.includes(3, 5)); // true(索引 5 就是 3)

// 从索引 6 开始查找 3
console.log(numbers.includes(3, 6)); // false(后面没有 3 了)

📌 小技巧:如果 fromIndex 是负数,它会从数组末尾倒数计算。例如 includes(x, -3) 相当于从倒数第 3 个元素开始往前找。

const colors = ['red', 'green', 'blue', 'yellow', 'purple'];

console.log(colors.includes('blue', -3)); // true(倒数第 3 个是 blue)

对象与引用类型:注意比较的是引用地址

当数组中存储的是对象时,includes() 比较的是引用地址,而不是对象的内容。

const user1 = { name: 'Alice', age: 25 };
const user2 = { name: 'Bob', age: 30 };
const user3 = { name: 'Alice', age: 25 };

const users = [user1, user2];

// 检查是否包含 user3
console.log(users.includes(user3)); // false

// 虽然 user3 和 user1 内容一样,但它们是不同的对象实例
// 引用地址不同,所以不相等

❗ 重点提醒:如果你需要比较对象内容,不能直接用 includes(),必须手动遍历或使用深比较工具。


实际应用场景:项目中的常见需求

场景一:权限校验

在后台系统中,经常需要判断用户角色是否拥有某项权限。

const userRoles = ['admin', 'moderator'];
const requiredRoles = ['admin', 'editor'];

// 判断用户是否有任意一个所需角色
const hasPermission = requiredRoles.some(role => userRoles.includes(role));

console.log(hasPermission); // true(因为 admin 在 userRoles 中)

🔍 这里结合 some() 使用,可以实现“只要有一个角色匹配就通过”的逻辑。

场景二:表单输入校验

验证用户输入的选项是否在允许范围内。

const allowedOptions = ['small', 'medium', 'large'];

function validateSize(input) {
  if (allowedOptions.includes(input)) {
    console.log('输入合法');
    return true;
  } else {
    console.log('输入非法,请选择 small、medium 或 large');
    return false;
  }
}

validateSize('medium'); // 输入合法
validateSize('extra');  // 输入非法,请选择 small、medium 或 large

场景三:防重复添加

在购物车中添加商品时,防止重复添加。

const cart = ['iPhone', 'MacBook'];

function addToCart(item) {
  if (cart.includes(item)) {
    console.log(`${item} 已在购物车中,无需重复添加`);
    return;
  }

  cart.push(item);
  console.log(`${item} 已成功添加`);
}

addToCart('iPhone');  // iPhone 已在购物车中,无需重复添加
addToCart('AirPods'); // AirPods 已成功添加

性能对比:includes() vs indexOf()

虽然两者都能实现“查找是否存在”,但 includes() 更适合语义表达。

方法 返回值 是否支持 NaN 语义清晰度 适用场景
includes() true / false ✅ 支持 判断是否存在
indexOf() 索引值(-1 表示不存在) ❌ 不支持 需要获取位置时
const arr = [1, 2, NaN, 4];

// 正确做法:使用 includes 判断是否存在 NaN
console.log(arr.includes(NaN)); // true

// 错误做法:使用 indexOf,会返回 -1(误判)
console.log(arr.indexOf(NaN));  // -1

🚨 建议:只要你想判断“是否存在”,优先使用 includes()


常见误区与注意事项

误区一:误以为 includes() 能处理嵌套结构

const nested = [{ id: 1 }, { id: 2 }];

console.log(nested.includes({ id: 1 })); // false

即使对象内容相同,由于是不同引用,结果仍是 false。必须手动遍历或使用 find()

误区二:忽略类型差异

const data = [1, 2, '3'];

console.log(data.includes(3));    // false(数字 3 ≠ 字符串 '3')
console.log(data.includes('3'));  // true

严格相等意味着类型必须一致。


总结:掌握 JavaScript includes() 方法的关键点

JavaScript includes() 方法是一个简洁、高效、语义明确的数组查找工具。它不仅能处理基本数据类型,还能正确识别 NaN,是现代开发中不可或缺的一部分。

  • 用它判断元素是否存在,比 indexOf() 更直观
  • 支持 fromIndex 参数,灵活控制搜索范围
  • 注意对象比较依赖引用地址
  • 不要滥用在复杂结构的判断上,需结合其他方法使用

掌握这个方法,能让你的代码更清晰、更健壮,也更容易被他人理解。无论是初学者还是中级开发者,都值得熟练运用。

在日常编码中,遇到“是否存在”的问题,不妨先想一想:能不能用 includes() 来解决?答案很可能是——可以。