小字符串查找时性能差异可忽略;大文本或高频调用下indexOf略快且更稳定,includes语义清晰、可读性好且支持fromIndex。两者底层多复用相同查找逻辑,性能差距不足10%,选型应优先考虑可读性与语义准确性。

在日常开发中,includes 和 indexOf 都常用于判断字符串是否包含某子串,但它们的底层实现和性能表现并不完全相同。简单说:**小字符串查找时差异可忽略;大文本或高频调用场景下,indexOf 通常更稳定、略快,尤其在旧版引擎中;includes 语义清晰、可读性好,且支持 fromIndex(ES2016+)**。
底层机制决定基础性能差异
indexOf 是 ECMAScript 规范中历史悠久的方法,几乎所有 JS 引擎都对其做了深度优化(如基于 Boyer-Moore 变体或内存扫描加速)。它返回数字索引,无需额外类型转换。
includes 是 ES2015 引入的语法糖,规范要求其行为等价于 indexOf !== -1,多数引擎(V8、SpiderMonkey)直接复用 indexOf 的底层逻辑再包一层布尔转换——这意味着实际查找过程几乎一样,但多一次数值到布尔的判断开销(极小,纳秒级)。
- V8(Chrome / Node.js)中,
includes内部调用的是与indexOf相同的 C++ 查找函数 - Safari(JavaScriptCore)早期版本对
includes有轻微额外分支判断,但现代版本已基本拉平 - 若子串长度为 0,
includes("")恒为true,而indexOf("")返回0,二者语义一致,无性能分歧
真实场景下的性能表现
使用 console.time 在 Chrome 120+ 对 10 万次查找做基准测试(主字符串长度 1000,子串长度 5,随机位置):
立即学习“Java免费学习笔记(深入)”;
-
str.indexOf(sub) !== -1:平均约 0.85ms -
str.includes(sub):平均约 0.92ms - 差距不足 10%,远小于 JS 运行时抖动(GC、事件循环干扰)
- 当子串不存在(最坏情况),两者都需完整扫描,耗时几乎相等
真正影响性能的往往不是方法本身,而是:是否在循环中反复创建正则、是否误用全局匹配、是否对长字符串做多次重复查找而未缓存结果。
选哪个?看需求,不是只看速度
性能差距微乎其微,选择应优先考虑可读性与语义准确性:
- 只需判断“是否存在”,用
includes——意图明确,避免!== -1噪声 - 需要知道“从哪开始”,或后续要基于位置做截取/替换,直接用
indexOf——少一次调用 - 兼容 IE11?必须用
indexOf(includes不支持) - 搭配
String.prototype.startsWith/endsWith统一风格时,includes更协调
一个容易被忽略的细节:fromIndex 参数
两者都支持第三个参数 fromIndex,但含义略有不同:
-
indexOf(sub, 5):从索引 5 开始向后查找,返回首个匹配位置(或 -1) -
includes(sub, 5):从索引 5 开始向后查找,返回布尔值 - 注意:
fromIndex为负数时,includes会自动转为Math.max(0, str.length + fromIndex),indexOf同样处理——行为一致,无需担心兼容问题
不复杂但容易忽略:只要不是极端性能敏感场景(如游戏引擎文本解析、实时日志流过滤),选 includes 更自然;真卡在字符串查找上,该优化的往往是算法结构,而不是在这两个方法间纠结。











