JS中indexOf、includes底层实现及性能测试负数值问题咨询
indexOf与includes相关问题解答 1 底层运行逻辑
- 按照ECMAScript标准定义,
Array.prototype.indexOf和Array.prototype.includes的默认实现都是线性遍历数组来匹配目标元素,通用场景下没有特殊的哈希索引或者预存结构优化,会遍历到匹配元素或者数组末尾才结束,仅部分JS引擎会针对极特殊场景做自定义优化。 - 二者核心差异是比较规则:
indexOf使用严格相等(===)做匹配,无法识别NaN;includes使用SameValueZero规则做匹配,可以正确匹配NaN,对空字符串、数组空槽位的匹配逻辑也和indexOf有细微区别。 - 你测试场景中
includes更快是因为Google Apps Script基于V8引擎运行,V8对includes的短字符串匹配(尤其是空字符串这类高频目标)做了专门的快速路径优化,匹配开销比indexOf的严格相等路径更低。
2 时间差为负数的原因
该问题核心是计时方法错误:
new Date().getMilliseconds()仅返回当前时间的毫秒部分(取值范围0-999),不是完整的时间戳。如果测试过程中跨越了秒级边界,比如开始计时时毫秒位是990,结束时是下一秒的15毫秒,计算得到的差值就是15 - 990 = -975,这就是负数的直接来源。- 次要影响因素是JS单线程执行的调度逻辑:测试过程中如果触发了引擎垃圾回收、系统后台任务抢占时间片,也会导致计时结果出现偏差,但不会稳定出现负数。
- 修正方法:将
getMilliseconds()替换为getTime()获取完整的毫秒级时间戳,或者使用环境支持的performance.now()做高精度计时,同时建议给所有局部变量加上声明,避免全局变量挂载带来的额外开销。
修正后测试代码示例:
function myFunction() { const array = [1, 2, 3, "", 5]; const t0 = new Date().getTime(); let j = 0; while(j < 10000000) { const x = array.indexOf("") > -1; j++; } const t1 = new Date().getTime(); console.log(`Call to indexOf took ${t1 - t0} milliseconds.`); let i = 0; const t2 = new Date().getTime(); while(i < 10000000) { const y = array.includes(""); i++; } const t3 = new Date().getTime(); console.log(`Call to includes took ${t3 - t2} milliseconds.`); }
3 学习资源搜索建议
可使用以下关键词搜索获取相关资料:
- ECMA-262 规范 Array.prototype.indexOf / includes 定义
- V8 引擎 Array 方法实现源码
- JS 数组方法性能对比测试
内容的提问来源于stack exchange,提问作者NightEye
相关产品推荐
相关产品推荐

