文章目录
- 💯前言
- 💯什么是`indexOf()`方法?
- 参数解释
- 返回值
- 示例
- 💯`indexOf()` 方法的工作原理
- 💯特殊案例:`undefined` 的处理
- 示例代码
- 图示解释
- 💯`indexOf()` 在字符串中的应用
- 特殊情况分析
- 1. 查找空字符串的行为
- 2. 超出长度范围的起始位置
- 3. 查找其他字符串时的行为
- 代码总结与逻辑理解
- 典型应用场景
- 💯`indexOf()` 在数组中的应用
- 示例
- 注意事项
- 💯查找的起始位置:`fromIndex`
- `fromIndex` 超出范围
- 💯 经典误区与陷阱
- 误区 1:省略参数
- 误区 2:查找 `NaN`
- 误区 3:`fromIndex` 的使用
- 💯 实际应用场景
- 场景 1:判断字符串是否包含子字符串
- 场景 2:去除数组中的重复元素
- 💯与 `includes()` 方法的比较
- 💯小结
💯前言
- 在编写 JavaScript 代码时,理解字符串和数组的查找操作是非常重要的,而
indexOf()
方法就是其中一个常用的方法。它在字符串或数组中查找指定元素的位置,如果找到则返回索引,如果找不到则返回-1
。本文将详细介绍indexOf()
的基础概念、用法及其背后的工作机制,帮助你深入了解它的行为。
JavaScript
💯什么是indexOf()
方法?
indexOf()
是 JavaScript 中用来在字符串或数组中查找某个子字符串或元素的方法。其基本形式为:
str.indexOf(searchValue[, fromIndex])
参数解释
searchValue
是必须要提供的参数,即你想要查找的字符串。fromIndex
是可选参数,用于指定从哪个索引开始查找。如果你不提供fromIndex
,默认值就是从索引0
开始查找。
在这段代码 str.indexOf(searchValue[, fromIndex])
中,中括号表示 可选参数,而不是语法的一部分。中括号 [ ]
用于表示这个参数不是强制的,开发者可以选择是否提供。如果你不提供 fromIndex
,查找将从字符串或数组的开头开始。这个表示方法是文档中的惯例,主要用于向开发者说明哪些参数是可选的,而不是代码中实际需要写中括号。
返回值
- 如果找到
searchValue
,返回它在字符串或数组中的首次出现的位置索引。 - 如果没有找到,返回
-1
。
示例
let str = 'hello world';
console.log(str.indexOf('world')); // 输出:6
console.log(str.indexOf('js')); // 输出:-1
在这个例子中,indexOf('world')
返回了索引 6
,因为 world
从索引 6
开始出现。而查找字符串 js
,由于它不在 str
中,因此返回了 -1
。
💯indexOf()
方法的工作原理
当调用 indexOf()
方法时,它会遍历字符串或数组,从 fromIndex
开始,依次与 searchValue
进行比较。如果找到完全匹配的部分,就返回匹配部分的起始位置索引;如果遍历完成后仍未找到匹配项,则返回 -1
。
以下是 indexOf()
的一个示例:
let array = [1, 2, 3, 4, 5];
console.log(array.indexOf(3)); // 输出:2
console.log(array.indexOf(6)); // 输出:-1
console.log(array.indexOf(2, 2)); // 输出:-1
在这个示例中:
- 查找
3
成功,返回它在数组中的位置2
。 - 查找
6
失败,返回-1
。 - 从索引
2
开始查找2
失败,因为从索引2
开始并没有元素2
。
💯特殊案例:undefined
的处理
在 JavaScript 中,如果 indexOf()
方法没有传入 searchValue
,那么默认会将其强制设置为字符串 "undefined"
。这种行为可能会引发一些意想不到的结果。
示例代码
console.log('undefined'.indexOf()); // 输出:0
console.log('undefine'.indexOf()); // 输出:-1
上面这段代码输出的结果可能会让人困惑,我们来逐行分析:
-
'undefined'.indexOf()
- 由于没有传入
searchValue
,JavaScript 强制将其设置为字符串"undefined"
。 - 当前字符串为
'undefined'
,而查找"undefined"
会在索引0
处找到匹配,因此返回0
。
- 由于没有传入
-
'undefine'.indexOf()
- 同样地,
searchValue
被设置为"undefined"
。 - 但是,当前字符串为
'undefine'
(少了最后一个字母d
),所以找不到完全匹配的"undefined"
,因此返回-1
。
- 同样地,
图示解释
在截图中,我们看到了 JavaScript 的一些行为:
console.log('undefined'.indexOf()); // 0
- 这里由于默认查找
"undefined"
,而字符串本身就是'undefined'
,所以结果是0
。
- 这里由于默认查找
console.log('undefine'.indexOf()); // -1
- 因为
'undefine'
中并没有完整的"undefined"
,结果是-1
。
- 因为
这个行为说明了 JavaScript 对于省略参数时的特殊处理机制。在代码中如果不小心省略了参数,可能会导致一些意料之外的结果。因此,显式地传递参数是一个良好的编程习惯。
💯indexOf()
在字符串中的应用
indexOf
方法用于查找某个字符串在另一个字符串中的位置。它接收两个参数:
- 要查找的字符串(第一个参数):这是你想在原字符串中搜索的内容。
- 起始位置(可选的第二个参数):从原字符串的某个索引位置开始查找,默认值是
0
。该参数是可选的。
该方法的返回值是查找到的字符串的索引值(首次出现的位置),如果没有找到,则返回 -1
。这是比较常见的用法。
例如:
var plants = '西红柿,黄瓜,芹菜,豆角,土豆,黄瓜';
console.log(plants.indexOf('黄瓜')); // 输出:4
console.log(plants.indexOf('芹菜')); // 输出:9
console.log(plants.indexOf('苹果')); // 输出:-1 (因为不存在“苹果”)
上面的代码输出的是找到的子字符串在原字符串中的位置索引。
特殊情况分析
在某些情况下,使用 indexOf
查找空字符串(''
)时,尤其是传入一个超出字符串长度的起始位置,indexOf
的行为与查找非空字符串时有所不同。这些特殊情况可以被总结如下:
1. 查找空字符串的行为
在 JavaScript 中,空字符串在任何字符串中被认为“存在”。实际上,空字符串在每一个索引位置上都可以找到,包括字符串的开头和末尾。因此,当使用 indexOf('')
时,结果往往会是指定位置的索引。
例如:
var plants = '西红柿,黄瓜,芹菜,豆角,土豆,黄瓜';
console.log(plants.indexOf('')); // 输出:0
上述代码的结果为 0
,因为空字符串可以视为在原字符串的开头存在。
2. 超出长度范围的起始位置
当我们在 indexOf
中指定的起始位置超过字符串的实际长度时,JavaScript 不会报错,而是会执行一种特定行为:
- 如果查找的是空字符串(
''
),indexOf
会返回字符串的长度值。
考虑以下代码:
var plants = '西红柿,黄瓜,芹菜,豆角,土豆,黄瓜'; // 字符串长度为 18
console.log(plants.indexOf('', 19)); // 输出:18
在这段代码中,我们在 indexOf
中传入了一个空字符串 ''
,并且起始位置设置为 19
,即超出了原字符串的长度(原字符串长度为 18
)。结果是返回了 18
,也就是原字符串的长度。
这种行为的原因在于 JavaScript 的 indexOf
机制:
- 在处理空字符串时,
indexOf
方法认为它可以在任何位置找到空字符串,包括在超出原字符串范围的“尾部”位置。因此,当起始位置超出原字符串的长度时,返回的结果是字符串的长度。
3. 查找其他字符串时的行为
与查找空字符串的情况不同,当使用超出长度范围的起始位置查找非空字符串时,indexOf
会返回 -1
,表示没有找到匹配项。这是因为,起始位置超出字符串长度后,已经没有更多字符可供查找。
例如:
console.log(plants.indexOf('黄瓜', 19)); // 输出:-1
此代码中,字符串 '黄瓜'
在起始位置 19
之后无法找到,所以返回 -1
。
代码总结与逻辑理解
这种行为的逻辑可以总结如下:
- 当查找的是空字符串时,
indexOf
会返回给定起始位置的索引。如果起始位置超出字符串的长度,则返回字符串的长度。 - 当查找的是非空字符串且起始位置超出字符串长度时,
indexOf
返回-1
,因为无法在起始位置之后找到任何匹配项。
理解这种行为对于 JavaScript 编程非常重要,特别是在处理可能涉及空字符串或需要从特定位置开始查找的场景时。这种特殊情况也提醒我们,要谨慎使用超出范围的起始位置,尤其是在不确定字符串长度的情况下。
典型应用场景
- 查找字符串的开头或结尾:可以使用空字符串来确定字符串的开头和末尾位置。
- 判断字符串是否为空:当使用
indexOf('')
时,如果返回值为字符串长度,则可以判定起始位置超过了字符串有效部分。
💯indexOf()
在数组中的应用
indexOf()
不仅可以在字符串中使用,还可以在数组中使用,来查找数组元素的索引。
示例
let fruits = ['apple', 'banana', 'mango', 'orange'];
console.log(fruits.indexOf('mango')); // 输出:2
console.log(fruits.indexOf('grape')); // 输出:-1
在这个例子中:
- 查找
'mango'
成功,返回它在数组中的位置索引2
。 - 查找
'grape'
失败,因为数组中没有这个元素,返回-1
。
indexOf()
在数组中的查找原理与在字符串中的查找非常相似,都是从 fromIndex
开始,逐个查找直到找到匹配的项或者遍历到数组的末尾。
注意事项
-
类型严格比较:
indexOf()
使用的是严格相等(===
)来比较元素。因此,如果查找的元素类型不匹配,则不会找到。let numbers = [1, 2, 3, '4']; console.log(numbers.indexOf(4)); // 输出:-1 console.log(numbers.indexOf('4')); // 输出:3
在这个示例中,数组中虽然有
'4'
,但是4
和'4'
类型不同,导致查找数字4
失败。 -
NaN
的查找:对于数组中的NaN
值,indexOf()
由于使用严格相等比较,无法正确查找到NaN
。这是因为NaN !== NaN
,在 JavaScript 中NaN
被认为是不等于自身的。let arr = [NaN, 1, 2]; console.log(arr.indexOf(NaN)); // 输出:-1
如果需要查找
NaN
,可以使用Array.prototype.findIndex()
方法:console.log(arr.findIndex(Number.isNaN)); // 输出:0
💯查找的起始位置:fromIndex
indexOf()
的第二个参数 fromIndex
指定了查找的起始位置。如果没有提供,则默认为 0
,即从头开始查找。
let str = 'hello world, hello JavaScript';
console.log(str.indexOf('hello', 5)); // 输出:13
在这个例子中,indexOf('hello', 5)
从索引 5
开始查找,因此返回了第二个 'hello'
出现的位置 13
。
fromIndex
超出范围
- 如果
fromIndex
大于等于字符串或数组的长度,indexOf()
将返回-1
,表示未找到。 - 如果
fromIndex
是负数,则从字符串或数组末尾的偏移位置开始。
let str = 'hello';
console.log(str.indexOf('h', 10)); // 输出:-1
console.log(str.indexOf('e', -4)); // 输出:1
💯 经典误区与陷阱
误区 1:省略参数
当使用 indexOf()
时忘记传递 searchValue
,JavaScript 会将其设为 "undefined"
,这可能会带来一些意料之外的结果,尤其是在调试代码时。
误区 2:查找 NaN
如前文所述,indexOf()
不能正确查找到数组中的 NaN
。对于需要查找 NaN
的场景,可以选择 findIndex()
和 Number.isNaN
的组合。
误区 3:fromIndex
的使用
很多开发者在使用 fromIndex
时会忽略其作用,这可能导致在字符串或数组中查找不到期望的结果。需要特别注意 fromIndex
的范围及其负数的情况。
💯 实际应用场景
场景 1:判断字符串是否包含子字符串
使用 indexOf()
可以轻松判断一个字符串中是否包含另一个子字符串。例如:
let sentence = 'The quick brown fox jumps over the lazy dog';
if (sentence.indexOf('fox') !== -1) {console.log('包含子字符串 "fox"');
}
场景 2:去除数组中的重复元素
可以使用 indexOf()
来实现数组去重:
let numbers = [1, 2, 2, 3, 4, 4, 5];
let uniqueNumbers = [];
numbers.forEach(num => {if (uniqueNumbers.indexOf(num) === -1) {uniqueNumbers.push(num);}
});
console.log(uniqueNumbers); // 输出:[1, 2, 3, 4, 5]
💯与 includes()
方法的比较
JavaScript 中还有一个相似的方法 includes()
,它用于判断字符串或数组中是否包含某个元素。与 indexOf()
不同的是,includes()
只返回布尔值。
let fruits = ['apple', 'banana', 'mango'];
console.log(fruits.includes('banana')); // 输出:true
console.log(fruits.includes('grape')); // 输出:false
相较于 indexOf()
,includes()
更加简洁,适用于只需要判断是否存在的场景,而不需要知道具体索引。
💯小结
indexOf()
是 JavaScript 中一个非常实用的查找方法,它既可以用于字符串,也可以用于数组。在使用indexOf()
时,需要特别注意默认参数的行为、严格相等的比较方式以及fromIndex
的影响。掌握这些细节可以帮助开发者避免常见的陷阱,提高代码的健壮性和可维护性。