如何检查JavaScript数组中是否存在元素?从“能用就行”到“飞一般的速度”
\n\n你是否曾经在编写代码时,盯着一个数据数组突然愣住了?“这里面有我需要的那个吗?”——这个问题困扰着每一位开发者。在Stack Overflow上,How do I check if an array includes a value in JavaScript 这个话题已经积累了数百万的浏览量。这并非没有道理。看似一个简单的任务,但它的解决方案不仅影响代码的可读性,还关系到整个应用程序的运行速度。
\n\n今天,我们将全面解析检查JavaScript数组中元素是否存在的方法。我们不仅仅是展示这些方法——我们将进行一次真正的性能调查。你将了解何时使用 includes(),为什么 indexOf() 有时更快,以及 Set 如何能让你的代码速度提升数十倍。开始吧!
经典之作:Array.prototype.includes()
\n\n最现代、最易读的方法是 includes()。它出现在ES2016中,并迅速成为事实上的标准。为什么?因为它的名字本身就说明了一切。
\n\nconst fruits = ['apple', 'banana', 'mango', 'orange'];\nconst hasBanana = fruits.includes('banana');\nconsole.log(hasBanana); // true\n\nconst hasGrape = fruits.includes('grape');\nconsole.log(hasGrape); // false\n\n\n简单而优雅。includes() 使用严格比较 (===),因此请注意数据类型:
const numbers = [1, 2, 3];\nconsole.log(numbers.includes('1')); // false — 字符串不等于数字\n\n\n优点:
\n- \n
- 可读性 10/10 — 即使是新手也能理解代码 \n
- 能处理
NaN(与indexOf不同) \n - 所有现代浏览器都支持 \n
缺点:
\n- \n
- 线性复杂度 O(n) — 会遍历整个数组 \n
- 不适合需要查找元素索引的情况 \n
老将:Array.prototype.indexOf()
\n\n在 includes() 出现之前,所有人都使用 indexOf()。这个方法返回第一个找到的元素的索引,如果元素不存在则返回 -1。
const fruits = ['apple', 'banana', 'mango'];\nconst index = fruits.indexOf('banana');\nif (index !== -1) {\n console.log('元素在位置', index, '找到');\n} else {\n console.log('元素未找到');\n}\n\n\n很多人习惯了这种检查方式,它仍然有效。但有一个重要的细节:indexOf() 无法找到 NaN。
\n\nconst arr = [NaN];\nconsole.log(arr.indexOf(NaN)); // -1 — 找不到!\nconsole.log(arr.includes(NaN)); // true — 找到了\n\n\n这是因为在JavaScript中 NaN !== NaN,而 indexOf 使用严格比较。includes() 则使用 SameValueZero 算法,该算法能正确处理 NaN。
何时使用 indexOf?
\n- \n
- 如果你需要元素的索引,而不仅仅是存在与否 \n
- 如果你确定数组中不包含 NaN \n
- 在无法使用ES2016+的遗留代码中 \n
灵活的战士:Array.prototype.find() 和 findIndex()
\n\n当你需要检查的不仅仅是存在性,而是要满足某个条件时,find() 就派上用场了。它接受一个回调函数,并返回第一个满足条件的元素,如果没有则返回 undefined。
const users = [\n { id: 1, name: 'Alice', age: 25 },\n { id: 2, name: 'Bob', age: 30 },\n { id: 3, name: 'Charlie', age: 35 }\n];\n\nconst user = users.find(u => u.age > 28);\nconsole.log(user); // { id: 2, name: 'Bob', age: 30 }\n\n// 检查是否存在\nconst exists = users.find(u => u.id === 4) !== undefined;\nconsole.log(exists); // false