首页 > web前端 > js教程 > 正文

js怎么判断字符串是否包含子串

煙雲
发布: 2025-08-23 14:32:01
原创
607人浏览过

判断字符串是否包含子串最推荐使用includes(),因其语义清晰且直接返回布尔值;2. 若需获取子串位置或兼容旧浏览器,则选用indexof(),通过返回值是否为-1判断存在性;3. 对于复杂模式匹配或不区分大小写的查找,应使用正则表达式,其中test()方法适合布尔判断,match()可返回匹配详情;4. 实现不区分大小写查找时,可统一转换大小写后比较,或更优地使用正则表达式i标志;5. 需注意空字符串始终被视为包含、长字符串高频操作的性能影响、旧浏览器对includes()不支持及复杂unicode字符的处理限制,选择方法时应权衡需求、可读性与性能,最终方案需完整考虑场景并避免常见陷阱。

js怎么判断字符串是否包含子串

在JavaScript中判断一个字符串是否包含另一个子串,我们通常会用到几种内置方法:

String.prototype.includes()
登录后复制
String.prototype.indexOf()
登录后复制
,以及更灵活的正则表达式。选择哪种方法,很大程度上取决于你的具体需求——是仅仅需要一个布尔结果,还是需要子串出现的位置,亦或是更复杂的模式匹配。

解决方案

判断字符串是否包含子串,最直接且现代的方式是使用

includes()
登录后复制
方法。如果需要知道子串首次出现的位置,或者需要兼容旧版浏览器,
indexOf()
登录后复制
则是经典选择。而对于复杂的模式匹配或不区分大小写的查找,正则表达式则提供了强大的能力。

以下是具体的实现方式:

1. 使用

String.prototype.includes()
登录后复制

这是ES6引入的方法,也是我个人最推荐的,因为它语义最清晰,直接返回一个布尔值,表明是否找到了子串。

const mainString = "Hello, world! Welcome to JavaScript.";
const subString1 = "world";
const subString2 = "TypeScript";

console.log(mainString.includes(subString1)); // true
console.log(mainString.includes(subString2)); // false

// 也可以指定开始搜索的位置
console.log(mainString.includes("world", 10)); // false (从索引10开始,"world"在前面)
登录后复制

2. 使用

String.prototype.indexOf()
登录后复制

这是一个历史悠久的方法,如果找到子串,它会返回子串首次出现的索引位置;如果没有找到,则返回

-1
登录后复制
。你可以根据这个返回值来判断。

const mainString = "Hello, world! Welcome to JavaScript.";
const subString1 = "world";
const subString2 = "TypeScript";

console.log(mainString.indexOf(subString1)); // 7 (子串"world"从索引7开始)
console.log(mainString.indexOf(subString2)); // -1

// 判断是否包含
if (mainString.indexOf(subString1) !== -1) {
    console.log("包含子串:", subString1);
}

// 同样可以指定开始搜索的位置
console.log(mainString.indexOf("world", 10)); // -1
登录后复制

3. 使用正则表达式 (

RegExp.prototype.test()
登录后复制
String.prototype.match()
登录后复制
)

正则表达式提供了最强大的模式匹配能力,尤其当你需要进行复杂匹配(如不区分大小写、匹配多种模式等)时,它几乎是唯一的选择。

  • RegExp.prototype.test()
    登录后复制
    : 这是最适合判断是否包含的方法,因为它只返回一个布尔值,效率高。

    const mainString = "Hello, world! Welcome to JavaScript.";
    const pattern1 = /world/; // 匹配"world"
    const pattern2 = /TypeScript/; // 匹配"TypeScript"
    
    console.log(pattern1.test(mainString)); // true
    console.log(pattern2.test(mainString)); // false
    
    // 不区分大小写匹配
    const caseInsensitivePattern = /javascript/i; // 'i' 标志表示不区分大小写
    console.log(caseInsensitivePattern.test(mainString)); // true
    登录后复制
  • String.prototype.match()
    登录后复制
    : 这个方法返回一个数组,包含所有匹配的结果(如果使用
    g
    登录后复制
    全局标志),或者
    null
    登录后复制
    如果没有找到。虽然也能用来判断,但通常比
    test()
    登录后复制
    返回更多信息,如果只需要判断是否存在,
    test()
    登录后复制
    更直接。

    const mainString = "Hello, world! Welcome to JavaScript.";
    const pattern1 = /world/;
    const pattern2 = /TypeScript/;
    
    console.log(mainString.match(pattern1)); // ["world", index: 7, input: "...", groups: undefined]
    console.log(mainString.match(pattern2)); // null
    
    if (mainString.match(pattern1)) {
        console.log("包含子串 (通过match):", pattern1);
    }
    登录后复制

JavaScript中
includes()
登录后复制
indexOf()
登录后复制
和正则表达式,我该如何选择?

在我看来,选择哪种方法,确实是一个需要结合场景和个人偏好的问题。我经常会遇到这样的决策点。

如果你只是想简单地知道“有没有”某个子串,而且你的目标环境支持ES6(现在绝大多数现代浏览器和Node.js都支持),那么

String.prototype.includes()
登录后复制
无疑是最佳选择。它的代码可读性极高,一眼就能看出意图,而且语义清晰,返回的就是一个布尔值,省去了
!== -1
登录后复制
的判断。这在日常开发中,能省下不少心力。

String.prototype.indexOf()
登录后复制
,虽然稍微啰嗦一点,需要你额外判断返回值是否为
-1
登录后复制
,但它有一个独特的优势:它能告诉你子串第一次出现的位置。有时候,我不仅想知道有没有,还想知道“在哪里”,比如我想在找到子串后,从那个位置开始截取或者替换,这时候
indexOf()
登录后复制
就派上用场了。而且,如果你还在维护一些古老的项目,或者需要兼容IE浏览器,那么
indexOf()
登录后复制
就是你的可靠伙伴,因为它兼容性非常好。

至于正则表达式,那简直是字符串匹配领域的瑞士军刀。如果你的需求不仅仅是简单的子串匹配,比如你需要:

  • 不区分大小写地查找(例如,查找"javascript"而不论大小写)。
  • 查找符合特定模式的字符串(例如,查找所有数字、邮箱地址、URL等)。
  • 查找多个可能的子串中的任意一个。
  • 替换匹配到的模式。

这时候,

includes()
登录后复制
indexOf()
登录后复制
就显得力不从心了,正则表达式的强大之处才能真正体现出来。虽然它的语法可能初看起来有点晦涩,但一旦掌握,你会发现它能解决很多复杂的字符串处理问题。我个人在处理表单验证、文本解析时,几乎离不开它。当然,对于非常简单的匹配,用正则可能会有点“杀鸡用牛刀”的感觉,而且性能上可能不如直接的字符串方法。所以,我的原则是:简单需求用
includes()
登录后复制
,需要位置用
indexOf()
登录后复制
,复杂模式匹配果断上正则。

如何在JavaScript中实现不区分大小写的子串查找?

实现不区分大小写的子串查找,这在实际开发中非常常见,比如搜索功能,用户输入“apple”,你希望也能匹配到“Apple”或者“APPLE”。这里有几种方法,我通常会根据具体情况来选择。

1. 使用

toLowerCase()
登录后复制
toUpperCase()
登录后复制
转换后再比较

阿里云-虚拟数字人
阿里云-虚拟数字人

阿里云-虚拟数字人是什么? ...

阿里云-虚拟数字人 2
查看详情 阿里云-虚拟数字人

这是最直观也最容易理解的方法,适用于

includes()
登录后复制
indexOf()
登录后复制
。它的核心思想是:将主字符串和要查找的子串都转换为统一的大小写(全部小写或全部大写),然后再进行比较。

const mainString = "Hello, JavaScript! Welcome to My Website.";
const searchLower = "javascript";
const searchUpper = "JAVASCRIPT";

// 转换为小写后使用 includes()
console.log(mainString.toLowerCase().includes(searchLower.toLowerCase())); // true
console.log(mainString.toLowerCase().includes(searchUpper.toLowerCase())); // true

// 转换为大写后使用 indexOf()
console.log(mainString.toUpperCase().indexOf(searchLower.toUpperCase()) !== -1); // true
console.log(mainString.toUpperCase().indexOf(searchUpper.toUpperCase()) !== -1); // true
登录后复制

这种方法的优点是简单易懂,兼容性好。但缺点是,如果你的主字符串非常长,或者你需要进行大量的查找操作,每次都对字符串进行

toLowerCase()
登录后复制
toUpperCase()
登录后复制
操作可能会带来一定的性能开销,因为它会创建一个新的字符串。在大多数Web应用场景下,这种开销通常可以忽略不计,但在性能敏感的场景下,可能需要考虑。

2. 使用正则表达式的

i
登录后复制
标志

这是处理不区分大小写匹配的“王道”方法,也是我个人最推荐的,尤其当你不只是判断包含,还可能涉及到更复杂的模式匹配时。正则表达式提供了一个

i
登录后复制
(ignore case)标志,直接告诉引擎在匹配时忽略大小写。

const mainString = "Hello, JavaScript! Welcome to My Website.";
const pattern = /javascript/i; // 'i' 标志表示不区分大小写

console.log(pattern.test(mainString)); // true
console.log(mainString.match(pattern)); // ["JavaScript", index: 7, input: "...", groups: undefined]

const anotherPattern = /website/i;
console.log(anotherPattern.test(mainString)); // true
登录后复制

使用正则表达式的

i
登录后复制
标志,代码更简洁,意图更明确。它直接在匹配层面解决了大小写问题,避免了创建新的字符串。对于复杂的模式,比如你不仅要不区分大小写,还要匹配“JS”或“Javascript”中的任意一个,正则表达式的优势就更加明显了:
/js(cript)?/i
登录后复制
。在我看来,只要涉及到不区分大小写,正则表达式几乎总是我的首选,除非是那种极其简单的、不需要任何模式的纯子串查找,我才会考虑
toLowerCase()
登录后复制

JavaScript查找子串时,有哪些常见的陷阱或性能考量?

在JavaScript中查找子串,虽然看似简单,但在实际开发中,确实会遇到一些需要注意的细节,甚至是一些不易察觉的“坑”,以及在特定场景下需要考虑的性能问题。

1. 空字符串的“陷阱”

这是一个我偶尔会忽略,但一旦遇到就可能导致逻辑错误的小细节。当你要查找的子串是一个空字符串(

""
登录后复制
)时,
includes()
登录后复制
indexOf()
登录后复制
的行为可能会让你感到意外:

const myString = "hello world";

console.log(myString.includes(""));    // true
console.log(myString.indexOf(""));     // 0
console.log("".includes(""));         // true
console.log("".indexOf(""));          // 0
登录后复制

includes("")
登录后复制
会返回
true
登录后复制
,而
indexOf("")
登录后复制
会返回
0
登录后复制
。这意味着,它们认为任何字符串都“包含”一个空字符串,并且空字符串总是在索引
0
登录后复制
处。这在大多数情况下是合理的(空字符串可以看作是任何字符串的子序列),但如果你的业务逻辑要求“只有当子串非空时才进行查找”,那么你就需要在调用这些方法之前,先对子串进行空字符串检查。我有时会忘记这一点,导致搜索结果不符合预期。

2. 性能考量:长字符串与高频操作

对于绝大多数前端应用场景,字符串查找的性能差异通常可以忽略不计。现代JavaScript引擎对这些内置方法都做了高度优化。然而,在以下特定情况下,你可能需要稍微留意:

  • 非常长的字符串: 如果你的主字符串有几十万甚至上百万个字符,并且你需要频繁地对其进行子串查找操作,那么不同方法的性能差异可能会显现出来。例如,
    toLowerCase()
    登录后复制
    toUpperCase()
    登录后复制
    会创建新的字符串,这会消耗内存和CPU。
  • 循环中的查找: 如果你在一个大型循环中,对大量字符串或同一个长字符串进行重复的子串查找,即使单次操作很快,累积起来的开销也可能变得显著。

在这种极端情况下,通常

indexOf()
登录后复制
includes()
登录后复制
会比正则表达式稍微快一些,因为它们是针对特定任务优化的。而正则表达式虽然功能强大,但其解析和匹配过程相对复杂,对于简单的纯子串查找,性能可能会略逊一筹。但话说回来,除非你真的遇到了性能瓶颈,否则我通常建议优先考虑代码的可读性和维护性。过早的优化往往是万恶之源。

3. 浏览器兼容性(历史遗留问题)

虽然现在已经不是大问题了,但如果你需要支持非常老的浏览器(比如IE11或更早),

String.prototype.includes()
登录后复制
是ES6(ECMAScript 2015)才引入的。这意味着在这些旧环境中,它将不可用。

// 在不支持ES6的环境中,这会抛出TypeError
// "abc".includes("b")
登录后复制

在过去,为了兼容性,我们通常会使用

indexOf() !== -1
登录后复制
来替代
includes()
登录后复制
。或者,你可以通过Polyfill来为旧浏览器添加
includes()
登录后复制
的支持。不过,随着浏览器更新迭代,现在很少需要为此特别担心了。但我偶尔还是会遇到一些遗留系统,需要我保持警惕。

4. Unicode与复杂字符集

JavaScript的字符串方法通常能很好地处理Unicode字符。例如,

"你好世界".includes("世界")
登录后复制
会正常工作。然而,对于一些更复杂的Unicode情况,比如组合字符(如
登录后复制
,它可能由
e
登录后复制
´
登录后复制
两个码点组成),或者一些特殊的语言环境下的字符匹配规则,简单的
includes()
登录后复制
indexOf()
登录后复制
可能无法满足所有需求。在这种情况下,可能需要借助更专业的Unicode库,或者更复杂的正则表达式模式。这通常是比较高级的场景,一般开发中较少遇到。

总的来说,在日常开发中,

includes()
登录后复制
indexOf()
登录后复制
是你的首选,它们简单高效。当需要处理复杂模式或不区分大小写时,正则表达式是不可替代的。了解这些方法的细微差别和潜在的“坑”,能帮助你写出更健壮、更高效的代码。

以上就是js怎么判断字符串是否包含子串的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号