Array数组的indexOf、includes vs for-loop性能比较
最近遇到一道算法题,然后有些人会使用 includes
、indexOf
去判断是否存在另一个数。这让我不禁思考,这和 for loop
有什么区别,能减少时间复杂度吗?我一开始也不是很清楚,但我可以找文档,找标准。我的第一判断是 includes
完全和 for loop
没有区别的,只是es6 标准规范提供的语法糖,而 indexOf
还是有一定效率的。带着疑惑,查看 MDN 和 ecma-262
includes
includes
是 ES6 新增语法,返回 布尔值。最容易拿 indexOf
来比较, indexOf
不能判断 NaN
, 而且不够语义,返回的是 匹配值的位置 或 -1
。
includes
内部实现是这样的:
- Let O be ? ToObject(this value).
- Let len be ? ToLength(? Get(O, “length”)).
- If len is 0, return false.
- Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step produces the value 0.)
- If n ≥ 0, then
- Let k be n.
- Else n < 0,
- Let k be len + n.
- If k < 0, let k be 0.
- Repeat, while k < len
- Let elementK be the result of ? Get(O, ! ToString(k)).
- If SameValueZero(searchElement, elementK) is true, return true.
- Increase k by 1.
- Return false.
其中的 SameValueZero
内部实现是这样的:
- If Type(x) is different from Type(y), return false.
- If Type(x) is Number, then
- If x is NaN and y is NaN, return true.
- If x is +0 and y is -0, return true.
- If x is -0 and y is +0, return true.
- If x is the same Number value as y, return true.
- Return false.
- Return SameValueNonNumber(x, y).
从上面可以看出 includes
内部是使用 while
循环,并不能够降低时间复杂度。它能判断出 NaN
以及 +0
等于-0
。
所以,返回值的语义化和 NaN
的判断就是 includes
的场景。
indexOf
好,includes
用来提升效率的幻想破灭了,那 indexOf
呢,规范是这么写的:
- Let O be ? ToObject(this value).
- Let len be ? ToLength(? Get(O, “length”)).
- If len is 0, return -1.
- Let n be ? ToInteger(fromIndex). (If fromIndex is undefined, this step produces the value 0.)
- If n ≥ len, return -1.
- If n ≥ 0, then
- If n is -0, let k be +0; else let k be n.
- Else n < 0,
- Let k be len + n.
- If k < 0, let k be 0.
- Repeat, while k < len
- Let kPresent be ? HasProperty(O, ! ToString(k)).
- If kPresent is true, then
- Let elementK be ? Get(O, ! ToString(k)).
- Let same be the result of performing Strict Equality Comparison searchElement === elementK.
- If same is true, return k.
- Increase k by 1.
- Return -1.
Array
的 indexOf
也使用了 while
循环,并使用 ===
全等比较。(注: 与 String.prototype.indexOf
并不同)
indexOf
使用场景是需要知道 匹配值的位置。
结论
这是一个性能测试比较
so? 如果单纯只是想比较,简单的才是最快的。 includes
与indexOf
效率相当,而for Loop
最快,因为没有其他的前置判断和浏览器对它的优化。