- Published on
如何在 JavaScript 中检查数组是否包含某个值?
- Authors
- Name
在 JavaScript 中,我们经常需要检查数组是否包含某个值。传统的做法是使用 indexOf
或 lastIndexOf
方法,但是这些方法在处理大型数组时性能并不理想。本文将介绍一种双向查找的方法,能够有效提高查找速度。
背景
虽然 includes 方法提供了一个便捷的接口,但是目前支持度还较低。因此,我们需要寻找一种替代 indexOf
和 lastIndexOf
的方法。
在众多优化方案中,@Damir Zekic 提出的 contains
函数表现最佳。然而,该方案的基准测试数据较为陈旧,可能不再适用。因此,我们提出了一种双向查找的方法,可以显著提升查找速度。
双向查找方法
通过在遍历数组时同时从两端进行比较,可以减少遍历次数,从而提高性能。下面是实现该方法的代码:
function bidirectionalIndexOf(a, b, c, d, e) {
for (c = a.length, d = c * 1; c--; ) {
if (a[c] == b) return c // 或者使用 a[c]===b
if (a[(e = d - 1 - c)] == b) return e // 或者使用 a[e=d-1-c]===b
}
return -1
}
// 用法示例
bidirectionalIndexOf(array, 'value')
该方法在实际应用中比传统方法快约两倍,特别适用于大型数组的查找操作。
性能测试
为了验证该方法的性能,我创建了一个包含 10 万个元素的数组,并进行了三次查找操作:在数组的开头、中间和结尾。性能测试结果可以访问以下链接:
数组原型变体
为了便于调用,我们还可以将该方法添加到数组的原型上:
Object.defineProperty(Array.prototype, 'bidirectionalIndexOf', {
value: function (b, c, d, e) {
for (c = this.length, d = c * 1; c--; ) {
if (this[c] == b) return c // 或者使用 this[c]===b
if (this[(e = d - 1 - c)] == b) return e // 或者使用 this[e=d-1-c]===b
}
return -1
},
writable: false,
enumerable: false,
})
// 用法示例
array.bidirectionalIndexOf('value')
我们还可以对该方法进行简单修改,使其返回 true
或 false
,如需返回匹配的对象、字符串或其他类型的数据,也可以进行对应调整。
另一个实现(while 循环)
另外,我们还可以使用 while
循环实现相同的功能:
function bidirectionalIndexOf(a, b, c, d) {
c = a.length
d = c - 1
while (c--) {
if (b === a[c]) return c
if (b === a[d - c]) return d - c
}
return c
}
// 用法示例
bidirectionalIndexOf(array, 'value')
为什么这种方法有效?
通过简单计算得到数组中的对称索引,比逐一遍历数组快两倍。
即使是更复杂的示例,每次迭代进行三次检查,这种方法依然表现优异。更详细的性能测试可以访问以下链接: