0%

javascript-search-in-array

Introduction

搜索数组中的元素是我们在日常开发中经常遇到的问题,本文将介绍 JavaScript 中搜索数组元素的几种方法。

Array.prototype.indexOf()

在ES6之前,我们通常使用indexOf方法来查找数组中的元素的下标。此函数多用于判断数组中是否存在某元素。
Array.prototype.indexOf() 方法返回给定元素的第一个索引,如果不存在,则返回 -1indexOf方法的语法如下:

1
2
indexOf(searchElement)
indexOf(searchElement, fromIndex)
  • searchElement:要查找的元素。
  • fromIndex:从该索引处开始查找。如果该值大于或等于数组的长度,则 indexOf 返回 -1,表示未找到。
1
2
3
const arr = [1, 2, 3, 4, 5];
const result = arr.indexOf(3);
console.log(result); // output: 2

indexOf的弊端是只能查找有确定值的元素,无法按条件查找,比如查找大于3的元素下标。

Array.prototype.find()

ES6引入了find方法,相比indexOf方法,find方法使用一个条件函数来查找数组中的元素。
Array.prototype.find() 方法返回数组中满足条件的第一个元素的值。如果找不到责则返回 undefinedfind一旦找到元素,立即停止查找并返回。find方法的语法如下:

1
2
find(callbackFn)
find(callbackFn, thisArg)

callbackFn 函数接收三个参数:

  • element:数组中当前正在处理的元素。
  • index:数组中当前正在处理的元素的索引。
  • array:调用 find 方法的数组。

以下代码查找数组中等于3的元素。

1
2
3
const arr = [1, 2, 3, 4, 5];
const result = arr.find(item => item === 3);
console.log(result); // output: 3

以下代码查找数组中大于3的元素。

1
2
3
const arr = [1, 2, 3, 4, 5];
const result = arr.find(item => item > 3);
console.log(result); // output: 4

由此可见find相比indexOf更加灵活:

  1. indexOf只能查找元素的下标,而find可以查找元素本身。
  2. indexOf只能查找有确定值的元素下标,而find可以按条件查找。

如果想按条件查找元素的下标该怎么办呢?这时候就需要用到findIndex方法。

Array.prototype.findIndex()

Array.prototype.findIndex() 该方法与find方法类似,只不过它不是返回元素,而是返回元素的下标。找不到则返回 -1findIndex一旦找到一个匹配,立即停止查找并返回。findIndex方法的语法如下:

1
2
findIndex(callbackFn)
findIndex(callbackFn, thisArg)

callbackFn 函数接收三个参数:

  • element:数组中当前正在处理的元素。
  • index:数组中当前正在处理的元素的索引。
  • array:调用 findIndex 方法的数组。
1
2
3
const arr = [1, 2, 3, 4, 5];
const result = arr.findIndex(item => item > 3);
console.log(result); // output: 3

Array.prototype.includes()

Array.prototype.includes() 方法用来判断一个数组是否包含一个指定的值,如果是返回 true,否则返回 falseincludes方法的语法如下:

1
2
includes(searchElement)
includes(searchElement, fromIndex)
  • searchElement:要查找的元素。
  • fromIndex:从该索引处开始查找。如果该值大于或等于数组的长度,则 includes 返回 false,表示未找到。
1
2
3
const arr = [1, 2, 3, 4, 5];
const result = arr.includes(3);
console.log(result); // output: true

注意:includes方法只能判断特定值,而不能按条件判断,比如判断数组中是否有大于3的元素,include做不到。

总结

比较方式:

  1. findfindIndex 方法是通过回调函数来判断元素是否满足条件。
  2. indexOf使用strict equal ===来判断元素是否相等。
  3. includes方法是通过 SameValueZero 算法来判断元素是否相等。

Sparsed Array的处理方式:

  1. indexOf会跳过稀疏数组中的空位。
  2. findIndexincludes 方法不会跳过稀疏数组中的空位。

undefinedNaN的处理方式:

  1. indexOf方法无法正确处理undefinedNaN
    1
    2
    [NaN].indexOf(NaN); // output: -1
    Array(1).indexOf(undefined); // output: -1
  2. includes方法可以正确处理undefinedNaN
    1
    2
    [NaN].includes(NaN); // true
    Array(1).includes(undefined); // true
  3. find/findIndex方法可以正确处理undefinedNaN吗?这取决于回调函数的具体实现。
    1
    2
    [NaN].find(x => Number.isNaN(x)); // OK
    Array(1).findIndex(x => x === undefined); // OK

使用场景

  1. 如果只需判断某元素是否在数组中,使用includes方法。
  2. 如果需要对找到的元素做进一步处理,那么使用find方法。
  3. 如果需要按确定值查找元素下标,使用indexOf方法。
  4. 如果需要根据条件查找数组中的元素的下标,使用findIndex方法。