Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说字符串/数组的includes和indexOf细节对比[亲测有效],希望能够帮助你!!!。
Tips字符串和数组都有includes和indexOf方法,且功能特性基本一致;
本文会先介绍数组的includes和indexOf,随后提一下这两个方法在字符串中有什么不同;
最后拓展一个indexOf的兄弟方法lastIndexOf
两者都是用于判断一个数组中是否存在某个值
includes,返回一个 布尔值
,存在返回true,不存在则返回false;
indexOf,返回被查找值在数组中 第一次出现的位置下标
,不存在则返回-1;
includes是ES6的语法,语义化更强,可判断是否存在 NaN;
由于indexOf内部使用的严格相等(===)进行判断,所以判断是否存在NaN时始终返回-1;
NaN:(Not-A-Number:不是一个数值数字),他表示的是一个数值范围,而不是一个具体的数值,所以NaN不等于任何值,包括他自己;
[NaN].indexOf(NaN); // -1
NaN == NaN // false
NaN === NaN // false ,不等于任何值包括自身
typeOf NaN; // number,数据类型是Number
NaN+1 // NaN,与任何值进行运算结果都是NaN
Boolean(NaN) // false,转换成布尔值是false
可以用全局方法 isNaN()
来判断,isNaN()方法会调用Number()方法试图将传入的参数转换成数值类型,转换成功返回false,失败就意味着参数不是一个数字,则返回true
于是空字符串和布尔值会被转转成0和1
isNaN(NaN) // true
isNaN(5) // false
isNaN('5') // false
isNaN('A') // true
Number('') // 0
Number(true) // 1
Number(false) // 1
isNaN('') // false
isNaN(true) // false
isNaN(true) // fasle
ES6提供了 Number.isNaN() 方法来判断一个值本身是否是NaN,不会调用Number()方法对参数进行转换,只有在参数是值为 NaN
的数字时,才会返回 true
Number.isNaN('123') // false 本身不是NaN
Number.isNaN('abc') // false 本身不是NaN
Number.isNaN(NaN) // true
Number.isNaN(Number.NaN); // true
Number.isNaN(0 / 0) // true
const arr = ['a', 'b', 'b', '2', 0, NaN,3]
// 查找值存在时,indexOf 返回该值的下标,includes 返回true
arr.indexOf('a') // 0
arr.includes('a') // true
// 查找值不存在时,indexOf返回 -1,includes返回false
arr.indexOf('c') // -1
arr.includes('c') //false
// 查找值在数组中出现多次时,indexOf返回第一次出现的位置下标,includes返回true
arr.indexOf('b') // 1
arr.includes('b') // true
// 都是严格比较,值和类型都要相等,且区分大小写,不区分+0和-0
arr.indexOf(2) // -1
arr.includes(2) // false
arr.indexOf('A') // -1
arr.includes('A') // false
arr.indexOf(+0) // 4
arr.indexOf(-0) // 4
arr.includes(+0) // true
arr.includes(-0) // true
// indexOf不能正确判断是否存在NaN,includes可以
arr.indexOf(NaN) // -1
arr.includes(NaN) // true
两者的第二个参数都是查找的起始下标
查找值在数组中但不在起始范围内则判断为不存在
const arr = ['a', 'b', 'b', '2', 0, NaN,3]
arr.indexOf('a',0) // 0
arr.includes('a',0) // true
arr.indexOf('a',1) // -1
arr.includes('a', 1) // false
// 起始下标大于等于数组长度时,不查找,直接判断为不存在
arr.indexOf(3,7) // -1
arr.includes(3, 7) // false
// 起始下标为负数时,表示从数组的倒数第几个开始查找
// 但查找顺序不变,依旧是从左往右 从前往后
// 如果负值的绝对值大于数组长度,起始下标重置成0,查找整个数组
arr.indexOf(3,-1) // 6,从倒数第一个开始从左往右找
arr.includes(3, -1) // true
arr.indexOf(0,-2) // -1,从倒数第二个开始从左往右找
arr.includes(0, -2) // false
arr.indexOf(0,-8) // 4,绝对值大于数组长度则整个数组都查找
arr.includes(0, -8) // true
在字符串中这两个方法的特性和数组基本一致,不一样的地方有一下几点
字符串的indexOf第一个参数如果不传,则会被强制设置成 "undefined"
const str = 'undefined'
const arr = ['undefined','a']
str.indexOf() // 0
str.indexOf('') // 0
arr.indexOf() // -1
字符串的indexOf第二个参数如果为负数则重置为0
const str = 'abcd'
const arr=['a','b','c','d']
str.indexOf('b', -2) // 1,从下标0开始查找
arr.indexOf('b',-2) // false,从倒数第二个开始查找
功能描述 lastIndexOf返回被查找值在数组或字符串中最后出现位置的下标;
也是数组和字符串都有的方法,这里依旧先以数组为例
不同点 既然是返回被查找值最后出现的位置,那么自然是从后往前找效率会更高些;
第一个参数是要查找的值,第二个参数是开始反向查找的下标,默认是数组长度减一(arr.length-1)
如果第二个参数大于或等于数组的长度,则查找整个数组
const arr = ['a', 'b', 'c', 'b', 'd']
const str = 'abcbd'
arr.lastIndexOf('b') // 3,默认从最后一个元素d开始,从右往左找
str.lastIndexOf('b') // 3
arr.lastIndexOf('b', 2) // 1,从下标2也就是c开始,从右往左找
str.lastIndexOf('b', 2) // 1
arr.lastIndexOf('b', 5) // 3,当第二个参数大于等于数组长度时,就从数组最后一位开始,从右往左找
arr.lastIndexOf('b', 10) // 3
str.lastIndexOf('b', 5) // 3
str.lastIndexOf('b', 10) // 3
// 如果是负数,表示从倒数的第几个元素开始,从右往左找
// 注意,+0、-0都视为 0,不存在倒数第0个,0就是从第一个开始
// 如果负值的绝对值大于数组的长度,则直接返回 -1
arr.lastIndexOf('b', -2) // 3,从数组倒数第二项开始,从右往左找
arr.lastIndexOf('b', -10) // -1,绝对值大于数组长度,直接返回 -1
arr.lastIndexOf('b', 0) // -1,从数组第一项开始,从右往左找
arr.lastIndexOf('a', 0) // 0
// 字符串的第一参数,如果是空字符串就返回被查字符串的长度
str.lastIndexOf('') // 5
// 字符串的第二个参数默认值是 +Infinity(正无穷)
// 如果大于等于字符串长度,则从字符串最后一位开始,从右往左找完
// 如果为负数,则重置为 0,从字符串的第一项开始,从右往左
str.lastIndexOf('a', -2) // 0
str.lastIndexOf('b', -2) // -1
str.lastIndexOf('a', 0) // 0
str.lastIndexOf('b', 0) // -1
// 字符串匹配完整字符,匹配成功时返回匹配的第一个字符下标
const str2 = 'abcbabc'
str2.lastIndexOf('ab') // 4,从最后一个字符往左匹配
str2.lastIndexOf('ab', 4) // 4,从下标为4的字符开始往左匹配,由于要匹配的是两个字符,
// 所以会把下标为5的字符加入匹配,匹配成功返回下标4
str2.lastIndexOf('abc', 4) // 4
如有错误请指正~
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。