JS中Array.indexOf用法详解及示例
时间:2025-08-05 09:40:29 182浏览 收藏
目前golang学习网上已经有很多关于文章的文章了,自己在初次阅读这些文章中,也见识到了很多学习思路;那么本文《JavaScript中Array.prototype.indexOf方法用于查找数组中某个元素的索引位置。如果找到该元素,返回其第一次出现的索引;如果未找到,则返回-1。语法:array.indexOf(searchElement[, fromIndex])参数说明:searchElement:要查找的元素。fromIndex(可选):从数组的哪个位置开始查找,默认为0。示例:const fruits = ['apple', 'banana', 'orange', 'banana']; console.log(fruits.indexOf('banana')); // 输出: 1 console.log(fruits.indexOf('banana', 2)); // 输出: 3 console.log(fruits.indexOf('grape')); // 输出: -1注意事项:该方法使用严格相等(===)进行比较。如果需要查找最后一个出现的位置,可以使用lastIndexOf()方法。这个方法在处理数组数据时非常实用,常用于判断元素是否存在或获取其位置。》,也希望能帮助到大家,如果阅读完后真的对你学习文章有帮助,欢迎动动手指,评论留言并分享~
1.indexOf方法用于查找数组中元素的首次出现位置,返回索引或-1。2.语法为arr.indexOf(searchElement[, fromIndex]),其中searchElement是要查找的元素,fromIndex是可选起始位置,默认从0开始,负数则从array.length + fromIndex计算。3.返回值为首次匹配的索引或-1,比较时使用严格相等(===),因此不适用于对象内容比较。4.与includes的区别在于indexOf返回索引而includes返回布尔值,前者适合需索引操作的场景,后者适合仅需判断存在的场景。5.indexOf无法基于对象属性查找,此时应使用findIndex或find方法。6.indexOf性能为O(n),适用于小数组,大数组或频繁查找可用Set或二分查找(需排序)。
JavaScript的Array.prototype.indexOf
方法是一个数组的内置功能,它的主要作用是帮助你查找一个给定元素在数组中首次出现的位置。简单来说,就是告诉你“这个东西在数组的第几个位置?”如果找到了,它会返回该元素对应的索引值(一个数字,从0开始计数);如果没找到,它就会返回-1。这是在JavaScript中进行数组元素查找的一个非常基础且常用的工具。

直接输出解决方案即可
要使用indexOf
,它的基本语法是这样的:arr.indexOf(searchElement[, fromIndex])
。

searchElement
:这是你想要在数组中查找的那个元素。它可以是任何类型的值,比如字符串、数字、布尔值,甚至是null
或undefined
。fromIndex
:这是一个可选参数。如果你提供了它,indexOf
就会从这个索引位置开始向后搜索。如果你不提供,它默认会从数组的第一个元素(索引0)开始搜索。- 如果
fromIndex
是一个负数,它会被当作array.length + fromIndex
来计算。举个例子,如果数组有5个元素,fromIndex
是-2,那么搜索就会从索引3(5 + -2)开始。 - 如果计算出来的起始索引超出了数组的范围(比如比数组长度还大),它会从数组末尾开始搜索,结果通常是找不到。
- 如果
它的返回值很明确:
- 如果找到了
searchElement
,就返回它在数组中首次出现的索引。 - 如果没找到,就返回-1。
来看几个例子,这样会更清楚:

const fruits = ['apple', 'banana', 'orange', 'apple', 'grape']; // 查找 'banana' 的位置 const index1 = fruits.indexOf('banana'); console.log(index1); // 输出: 1 (因为 'banana' 在索引1的位置) // 查找一个不存在的元素 'kiwi' const index2 = fruits.indexOf('kiwi'); console.log(index2); // 输出: -1 (因为 'kiwi' 不在数组中) // 从索引2开始查找 'apple' // 数组是 ['apple', 'banana', 'orange', 'apple', 'grape'] // 从 'orange' (索引2) 开始往后找,下一个 'apple' 在索引3 const index3 = fruits.indexOf('apple', 2); console.log(index3); // 输出: 3 // 从倒数第三个位置开始查找 'apple' // 数组长度是5,倒数第三个位置是 5 - 3 = 2 (即 'orange') const index4 = fruits.indexOf('apple', -3); console.log(index4); // 输出: 3 (和上面一样,都是从索引2开始找) // 查找 null 或 undefined const mixedArray = [1, null, 3, undefined, 5]; console.log(mixedArray.indexOf(null)); // 输出: 1 console.log(mixedArray.indexOf(undefined)); // 输出: 3
需要特别注意的是,indexOf
在比较元素时使用的是严格相等(===
)。这意味着它不仅比较值,还比较类型。比如,数字5
和字符串"5"
在indexOf
看来是不同的。
indexOf
和 includes
有什么区别?什么时候用哪个?
这确实是很多人会混淆的地方,因为它们都涉及“查找”这个动作。但它们的核心区别在于“返回什么”以及“你真正想知道什么”。
indexOf
,我们刚才已经详细说了,它返回的是元素在数组中的索引(一个数字),或者-1。它的目的是告诉你“这个东西在哪里?”或者“它在不在,如果在,具体在哪?”
而Array.prototype.includes()
方法则简单粗暴得多。它只返回一个布尔值(true
或false
)。它的目的就是回答一个简单的“是或否”问题:“这个数组里有没有这个东西?”
举个例子,就像你问一个朋友:“我的钥匙在哪里?”他可能会说:“在桌子上”(这就是indexOf
,告诉你具体位置)。但如果你问他:“我的钥匙在家里吗?”他只需要回答“是”或“否”(这就是includes
,只关心存在与否)。
那么,什么时候用哪个呢?
使用
indexOf
的场景:- 当你不仅想知道一个元素是否存在,还想知道它具体在哪个位置时。
- 当你需要根据元素的位置来执行后续操作时,比如使用
splice()
方法来删除或插入某个位置的元素。 - 当你需要处理数组中重复元素的情况,并且想找到第一个出现的那个时。
- 一个常见的模式是
if (arr.indexOf(element) !== -1)
,这表示如果元素存在,就执行某些操作。
使用
includes
的场景:- 当你只关心数组中是否存在某个元素,而不需要知道它具体在哪个位置时。
- 当你的代码逻辑只需要一个简单的真/假判断,而不需要索引值时,
includes
能让你的代码更简洁、更易读。 - 我个人在编写代码时,如果只是为了判断某个值是否存在,通常会优先选择
includes
,因为它表达的意图非常清晰,一眼就能看出是“包含检查”。
const items = ['pen', 'notebook', 'eraser']; // 场景1:我需要知道 "notebook" 在哪里,以便后续操作 const notebookIndex = items.indexOf('notebook'); if (notebookIndex !== -1) { console.log(`找到了笔记本,在索引 ${notebookIndex}。`); // 假设我要把笔记本换成新的 items.splice(notebookIndex, 1, 'new notebook'); console.log(items); // 输出: ['pen', 'new notebook', 'eraser'] } // 场景2:我只关心 "eraser" 有没有在列表里 if (items.includes('eraser')) { console.log('列表里有橡皮擦。'); } else { console.log('列表里没有橡皮擦。'); }
总的来说,选择哪个方法取决于你的具体需求。如果你只需要一个布尔值来判断存在性,includes
更简洁;如果你需要元素的具体位置,indexOf
则是你的首选。
indexOf
在处理复杂数据类型时有什么限制?
这是indexOf
一个非常重要的“坑”,或者说,是它的设计哲学所带来的限制。理解这一点对于避免一些难以发现的bug至关重要。
核心限制在于:indexOf
在比较元素时,使用的是严格相等(===
)。
这意味着什么呢?
对于原始数据类型(如数字、字符串、布尔值、null
、undefined
),indexOf
工作得非常好,因为它能准确地比较它们的值和类型。
但是,对于复杂数据类型,也就是对象(包括普通对象、数组、函数等),indexOf
不会去比较它们内部的属性值是否相同,它只会比较它们在内存中的引用地址是否相同。
举个例子你就明白了:
const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 3, name: 'Charlie' } ]; // 尝试查找一个与数组中第一个对象“看起来一样”的新对象 const searchUser1 = { id: 1, name: 'Alice' }; const foundIndex1 = users.indexOf(searchUser1); console.log(foundIndex1); // 输出: -1 // 为什么是 -1? // 因为 searchUser1 是一个全新的对象,虽然它的内容和 users[0] 一模一样, // 但它们在内存中是两个不同的对象实例,引用地址不同。 // indexOf 认为它们是不同的。 // 那么,如果我查找数组中已有的对象引用呢? const existingUser = users[0]; // 拿到数组中第一个对象的引用 const foundIndex2 = users.indexOf(existingUser); console.log(foundIndex2); // 输出: 0 // 这次是 0。因为 existingUser 和 users[0] 指向的是内存中的同一个对象。
这个限制在处理由后端API返回的数据时尤其常见。你从API拿到的可能是[{ id: 1, name: 'Alice' }]
,然后你本地又构造了一个{ id: 1, name: 'Alice' }
,你期望indexOf
能找到它,但结果往往是-1。
解决方案:
当你需要根据复杂对象的内容(例如,某个属性的值)来查找时,indexOf
就无能为力了。这时,你需要使用其他方法,最常用的是:
Array.prototype.findIndex()
: 这个方法接受一个回调函数作为参数。你可以在回调函数中定义你的查找逻辑,比如比较对象的某个属性。它会返回满足条件的第一个元素的索引,如果没找到则返回-1。const foundIndexById = users.findIndex(user => user.id === 2); console.log(foundIndexById); // 输出: 1 (找到了 id 为 2 的 Bob) const foundIndexByName = users.findIndex(user => user.name === 'Charlie'); console.log(foundIndexByName); // 输出: 2
Array.prototype.find()
: 类似findIndex
,但它返回的是满足条件的第一个元素本身,而不是它的索引。如果没找到则返回undefined
。const foundUser = users.find(user => user.id === 3); console.log(foundUser); // 输出: { id: 3, name: 'Charlie' }
对我个人来说,这个严格相等的问题在初期学习JavaScript时确实让我困惑了很久。你总觉得“明明内容都一样,为什么找不到?”直到深入理解了原始值和引用值的区别,以及===
的运作方式,才豁然开朗。所以,记住这个限制非常重要,它能帮你避免很多不必要的调试时间。
indexOf
的性能考量和替代方案
当我们谈论indexOf
的性能时,主要指的是它在查找元素时所采用的机制。indexOf
本质上执行的是一个线性搜索(或称顺序搜索)。这意味着它会从指定的fromIndex
开始,一个接一个地检查数组中的每个元素,直到找到目标元素或遍历完整个数组。
性能考量:
- 时间复杂度: 在最坏的情况下(目标元素在数组的末尾,或者根本不存在),
indexOf
需要检查数组中的所有元素。因此,它的时间复杂度是O(n),其中n是数组的长度。这意味着数组越大,查找所需的时间就可能越长。 - 适用场景: 对于小型数组(比如几十个或几百个元素),O(n)的性能通常可以忽略不计,
indexOf
用起来非常方便且足够快。但在处理非常大的数组(比如几万、几十万甚至上百万个元素)时,或者在性能敏感的应用中需要频繁地进行查找操作时,O(n)的线性搜索就可能成为一个性能瓶颈。
替代方案(在特定场景下可以提供更好的性能或功能):
Array.prototype.findIndex()
/Array.prototype.find()
:- 何时使用: 当你需要查找复杂数据类型(对象)时,或者需要根据更复杂的条件(而不仅仅是严格相等)来查找元素时。
- 性能: 它们同样执行线性搜索,所以时间复杂度也是O(n)。在性能上,它们和
indexOf
属于同一量级。但它们提供了更灵活的查找逻辑,可以弥补indexOf
在复杂类型查找上的不足。
使用
Set
进行存在性检查:- 何时使用: 如果你的主要需求是频繁地检查一个元素是否存在于一个大型集合中,并且这个集合中的元素是唯一的。
- 性能:
Set
是一种专门用于存储唯一值的集合。向Set
中添加元素(构建Set
)的时间复杂度是O(n)。但是,一旦Set
构建完成,使用Set.prototype.has()
方法来检查元素是否存在,平均时间复杂度可以达到惊人的O(1)(常数时间)!这意味着无论Set
有多大,查找一个元素所需的时间理论上都是固定的。 - 局限:
Set
只能存储原始值或对象的引用,同样不能进行基于对象内容(深比较)的查找。而且,构建Set
本身需要时间,所以只有当你需要对同一个数据集进行多次查找时,Set
的性能优势才能体现出来。const largeArray = Array.from({ length: 100000 }, (_, i) => `item-${i}`); const itemToSearch = 'item-99999'; // 查找最后一个元素
console.time('indexOf Search'); largeArray.indexOf(itemToSearch); console.timeEnd('indexOf Search'); // 对于大数组,这里可能会耗时
// 转换为 Set console.time('Set Creation'); const itemSet = new Set(largeArray); console.timeEnd('Set Creation'); // 创建 Set 需要 O(n) 时间
console.time('Set.has Search'); itemSet.has(itemToSearch); console.timeEnd('Set.has Search'); // 查找非常快
你会发现,对于单次查找,`indexOf`可能看起来更快(因为它不需要额外的Set构建时间),但如果进行成百上千次查找,`Set.has()`的累计优势会非常明显。
二分查找(Binary Search):
- 何时使用: 当你的数组是已排序的,并且你需要高效地查找元素时。
- 性能: 二分查找的时间复杂度是O(log n)。这是一个巨大的性能提升,尤其对于非常大的数组。例如,一个包含一百万个元素的数组,线性搜索可能需要一百万步,而二分查找只需要大约20步(log2(1,000,000) ≈ 19.9)。
- 局限: JavaScript原生并没有内置的二分查找方法。你需要自己实现它,或者引入一个工具库。更重要的是,它要求数组必须是已排序的。如果数组未排序,你需要先对其进行排序(排序本身通常是O(n log n)),这可能会抵消查找的性能优势。
我的经验是,不要过度优化。在绝大多数日常开发场景中,indexOf
的性能是完全足够的。只有当你遇到明显的性能瓶颈,并且通过性能分析工具(如浏览器开发者工具)确认是数组查找导致的问题时,才应该考虑上述的替代方案。选择“对的工具”而不是“最快的工具”往往能带来更好的开发效率和代码可读性。indexOf
就像你的瑞士军刀,虽然不是每个任务都最锋利,但它足够通用且可靠。
今天关于《JS中Array.indexOf用法详解及示例》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
306 收藏
-
135 收藏
-
422 收藏
-
205 收藏
-
317 收藏
-
441 收藏
-
410 收藏
-
470 收藏
-
404 收藏
-
443 收藏
-
297 收藏
-
406 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习