JavaScript 中 indexOf() 方法详解
indexOf() 是 JavaScript 中 数组(Array) 和 字符串(String) 原型对象上都内置的一个重要方法,用于查找指定元素或子字符串在原对象中首次出现的位置(索引)。如果找不到,则返回 -1。
1. 基本语法
字符串版:
string.indexOf(searchValue[, fromIndex])
数组版:
array.indexOf(searchElement[, fromIndex])
- searchValue / searchElement:要查找的值(字符串或数组元素)。必填。
- fromIndex(可选):从哪个索引开始查找。默认是
0。 - 如果
fromIndex >= 长度,直接返回-1(不搜索)。 - 如果
fromIndex < 0,则从max(长度 + fromIndex, 0)开始(支持负数索引,类似 Python)。
返回:首次匹配的索引(从 0 开始),找不到返回 -1。
2. 字符串中使用 indexOf()
const str = "Hello World, welcome to the World!";
// 基本用法
str.indexOf("World"); // 返回 6(第一次出现的位置)
str.indexOf("world"); // 返回 -1(区分大小写!)
str.indexOf("o"); // 返回 4(第一个 'o' 的位置)
// 指定起始位置
str.indexOf("o", 5); // 返回 8(从索引5开始找下一个 'o')
str.indexOf("World", 10); // 返回 29(第二次出现)
// 负数 fromIndex(从右往左计算)
str.indexOf("o", -5); // 等价于从 length-5 开始找,返回 31
// 不存在
str.indexOf("JavaScript"); // 返回 -1
注意事项:
- 区分大小写:
'A' !== 'a' - 类型转换:会自动将参数转为字符串(但不推荐依赖)
- 常用于判断字符串是否包含某子串:
if (str.indexOf("World") !== -1) {
console.log("包含 World");
}
// 现代推荐用 includes()
if (str.includes("World")) { ... }
3. 数组中使用 indexOf()
const fruits = ["apple", "banana", "orange", "apple", "grape"];
// 基本查找
fruits.indexOf("banana"); // 返回 1
fruits.indexOf("apple"); // 返回 0(只返回第一次出现的位置)
fruits.indexOf("pear"); // 返回 -1
// 指定起始位置
fruits.indexOf("apple", 1); // 返回 3(从索引1开始找下一个 apple)
// 查找对象(注意:严格相等 ===)
const objs = [{id: 1}, {id: 2}];
const obj = {id: 1};
objs.indexOf(obj); // 返回 -1(对象是引用类型,地址不同)
// 正确方式查找对象
const users = [{name: "Tom"}, {name: "Jerry"}];
const target = users[0];
users.indexOf(target); // 返回 0(同一个引用)
关键点:
- 使用 严格相等(===) 比较元素。
- 基本类型(字符串、数字、布尔)可以正常查找。
- 对象、数组等引用类型必须是同一个引用才能找到。
- NaN 无法通过 indexOf 找到(因为 NaN !== NaN):
[NaN].indexOf(NaN); // 返回 -1
4. 常见应用场景
| 场景 | 示例代码 |
|---|---|
| 判断是否存在 | if (arr.indexOf(item) > -1) { ... }(旧写法,现在推荐 includes()) |
| 查找并删除元素 | “`js |
| 字符串替换(简单版) | js let pos = str.indexOf("old"); if (pos !== -1) str = str.slice(0,pos) + "new" + str.slice(pos+"old".length); |
| 校验输入格式(如邮箱@符号) | if (email.indexOf("@") === -1) { error } |
| 实现简单去重(配合 filter) | js const unique = arr.filter((item, index) => arr.indexOf(item) === index); |
5. 与现代方法的对比(推荐使用新API)
| 方法 | 返回值 | 是否推荐 | 说明 |
|---|---|---|---|
indexOf() | 索引或 -1 | 一般 | 老方法,兼容性最好 |
includes() | true / false | 强烈推荐 | 语义更清晰:arr.includes(item) |
findIndex() | 索引或 -1 | 推荐 | 支持回调函数,可查找复杂条件(如对象属性) |
find() | 找到的元素或 undefined | 推荐 | 返回元素本身 |
lastIndexOf() | 从右往左查找的索引 | 偶尔用 | 查找最后一次出现的位置 |
示例对比:
// 旧写法
if (arr.indexOf("banana") !== -1) { ... }
// 新写法(推荐)
if (arr.includes("banana")) { ... }
// 查找对象
const idx = users.findIndex(user => user.name === "Tom");
6. 小技巧总结
- 负数 fromIndex 非常实用:
str.indexOf("x", -10)从倒数第10个字符开始找。 - 性能:在大数组中频繁调用 indexOf 可能较慢,可考虑 Map/Set 优化。
- 兼容性:indexOf 从 ES5(2009年)开始支持,所有现代浏览器和 Node.js 都支持。
掌握 indexOf() 是 JS 基础中的基础,虽然现在有更优雅的替代方法,但理解它有助于阅读旧代码和深入理解数组/字符串操作。
如果你有具体场景(如“如何用 indexOf 实现字符串多关键词搜索”),欢迎继续问!