本文汇总了JavaScript中判断数组是否包含指定元素的五种常用方法,包括for循环、indexOf、find/findIndex、some以及ES6新增的includes。文章详细对比了各方法的性能、语义清晰度及对NaN的特殊处理,并提供了低版本浏览器的兼容封装方案,帮助开发者根据实际需求选择最优实现。
在探索ES6数组扩展特性时,注意到新增了许多实用的数组方法。鉴于在实际开发中,判断数组是否包含特定元素是一项高频操作,本文对此进行系统梳理与总结。
使用for循环结合break语句
1. 使用for循环结合break语句
许多开发者首先想到的可能是for循环,因为这是最基础且稳妥的操作方式:
let arr = [1, 2, undefined, '听风是风', 'echo'],
i = 0;
const LENGTH = arr.length;
//初始化result状态,只要能找到匹配的则修改为true
let result = false;
for (; i < LENGTH; i++) {
if (arr[i] === '听风是风') {
result = true;
break;
};
};
if (result) {
//do something...
};
使用for循环的优势在于可以结合break语句。一旦找到满足条件的元素,即可立即跳出循环。例如,若第一个元素即符合条件,后续遍历步骤将被直接跳过,从而优化性能。
然而,for循环的缺点在于代码不够直观。在循环内部无法直接return查询结果,若需封装为函数,还需额外定义一个result变量来存储状态。
此外,虽然for循环能解决多数数组操作问题,但不应总是首选。除了for循环,探索更多数组高阶函数并思考其适用场景,往往能带来更优雅的解决方案。
提到循环,很多人会本能地联想到forEach。尽管forEach支持回调函数,但它既不能在回调中直接return,也无法使用break,因此此处不再赘述。
最后,for循环和forEach在处理NaN时并不实用。因为NaN是唯一一个不等于自身的值,虽然可以通过额外逻辑实现NaN及其他非NaN对象的判断,但实现过程较为繁琐。
使用Arr.indexOf()方法
2. 使用Arr.indexOf()方法
let arr = [1, 2, undefined, '听风是风', 'echo'];
//利用indexOf查找下标的特性
let result = arr.indexOf('听风是风');//3
if (result>-1) {
//do something...
};
indexOf方法会从头到尾检索数组,若找到第一个符合条件的元素则返回其下标,未找到则返回-1。因此,通过判断返回值是否大于等于0(即if(result>-1))即可确定元素是否存在。
与for循环相比,indexOf的写法更为简洁。但其缺点是无法在找到目标元素后停止检索,即使已找到所需元素,它仍会继续遍历剩余部分,这在性能上不够优化。
此外,该方法的语义化不够友好。我们的目的是判断数组是否包含某元素,而indexOf返回的是下标,这种间接判断方式略显别扭。同时,它对NaN的查找也不友好。
[NaN].indexOf(NaN);//-1
使用find()与findIndex()方法
3. 使用find()与findIndex()方法
let arr = [1, 2, undefined, '听风是风', 'echo'];
//利用indexOf查找下标的特性
let result = arr.find(ele => ele === '听风是风')//听风之风
if (result) {
//do something...
};
find方法是目前较为推荐的做法。它会查找并返回第一个符合条件的数组元素,若未找到则返回undefined。
需要注意的是,find在找到符合条件的对象后不会继续遍历,相当于自带了break操作。配合箭头函数简化回调,整体代码非常直观。
let arr = [1, 2, undefined, '听风是风', 'echo'];
//利用indexOf查找下标的特性
let result = arr.findIndex(ele => ele === '听风是风')//3
if (result>-1) {
//do something...
};
findIndex方法与find类似,区别在于它返回的是符合条件元素的下标而非元素本身。找到后同样会跳出循环,若未找到则返回-1,这一点与indexOf相似。
理想情况下,find方法可以结合Object.is()来判断NaN,同时也能判断其他对象,表现非常出色。
[NaN].find(ele => Object.is(NaN, ele)); //NaN [1].find(ele => Object.is(1, ele)); //1 [NaN].findIndex(ele => Object.is(NaN, ele)); //0 [1].findIndex(ele => Object.is(1, ele)); //0
这两种方法写法简洁,自带break机制,且能正确处理NaN,因此都比较推荐。
使用some()方法
4. 使用some()方法
let arr = [1, 2, undefined, '听风是风', 'echo'];
//利用indexOf查找下标的特性
let result = arr.some(ele => ele === '听风是风') //true
if (result) {
//do something...
};
some方法同样用于检测是否存在满足条件的元素。如果存在,则不再继续检索后续元素,直接返回true;若都不符合,则返回false。
其用法与find相似,区别在于find返回满足条件的元素,而some返回布尔值。从语义上看,判断“是否包含”直接返回布尔值更为贴切。
当然,some方法同样可以结合Object.is()来检测NaN。由于语义清晰且性能良好,some也是较为推荐的方法。
[NaN].some(ele => Object.is(NaN, ele));
使用includes()方法
5. 使用includes()方法
这是ES6新增的数组方法,专门用于检测数组是否包含某个元素。如果包含则返回true,否则返回false。其亮点在于可以直接检测NaN:
[1, 3, 'echo'].includes('echo'); //true [NaN, 3, 'echo'].includes(NaN); //true [1, 3, 'echo'].includes('听风是风'); //false
其优点显而易见,这是最简单且无需回调函数的做法,一个方法即可直接搞定。
缺点在于低版本浏览器的支持不够友好。如果环境允许,我们应优先使用;若不支持,则可通过封装实现兼容:
let hasEle = (() =>
Array.prototype.includes ?
(arr, val) => arr.includes(val) :
(arr, val) => arr.some(ele => Object.is(val, ele))
)();
hasEle([1, 2, NaN], 1) //true
hasEle([1, 2, NaN], NaN) //true
hasEle([1, 2, NaN], '听风是风') //false
希望本文的整理,能让您在未来查找数组元素时拥有更多灵活的选择。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。