JS `String.prototype.startsWith()` / `endsWith()` / `includes()`:更便捷的字符串查找

各位朋友,晚上好!我是老张,今晚咱们来聊聊JavaScript里那些帮你偷懒的字符串查找小助手:startsWith()endsWith()includes()。 它们就像是字符串界的“Ctrl+F”,但比“Ctrl+F”更灵活,更好用。准备好了吗?咱们这就开始!

一、远古时代:那些年我们用过的字符串查找方法

startsWith()endsWith()includes()这些“新潮”方法出现之前,咱们是怎么在字符串里“大海捞针”的呢? 主要靠indexOf()

indexOf() 方法返回指定值在字符串对象中首次出现的位置。如果没找到,就返回 -1。

const myString = "Hello World!";

// 查找 "World"
const index = myString.indexOf("World");
console.log(index); // 输出: 6

// 查找 "Universe" (不存在)
const notFound = myString.indexOf("Universe");
console.log(notFound); // 输出: -1

虽然 indexOf() 很好用,但你要判断字符串是否以某个子串开始结束,就得写一些额外的逻辑。

例如,判断字符串是否以 "Hello" 开头:

const myString = "Hello World!";

if (myString.indexOf("Hello") === 0) {
  console.log("字符串以 'Hello' 开头");
} else {
  console.log("字符串不以 'Hello' 开头");
}

判断字符串是否以 "!" 结尾,稍微复杂一点:

const myString = "Hello World!";
const target = "!";

if (myString.indexOf(target) === myString.length - target.length) {
  console.log("字符串以 '!' 结尾");
} else {
  console.log("字符串不以 '!' 结尾");
}

看到了吗?为了实现简单的开头和结尾判断,我们需要计算索引,比较长度,代码一下子就变得有点冗长了。

二、救星登场:startsWith()endsWith()includes()

ES6 带来了 startsWith()endsWith()includes() 这三个方法,简直是程序员的福音!它们让字符串查找变得更加直观,代码也更加简洁易懂。

  • startsWith():判断字符串是否以指定子串开头

    const myString = "Hello World!";
    
    console.log(myString.startsWith("Hello"));  // 输出: true
    console.log(myString.startsWith("World"));  // 输出: false
  • endsWith():判断字符串是否以指定子串结尾

    const myString = "Hello World!";
    
    console.log(myString.endsWith("!"));    // 输出: true
    console.log(myString.endsWith("World"));  // 输出: false
  • includes():判断字符串是否包含指定子串

    const myString = "Hello World!";
    
    console.log(myString.includes("World"));   // 输出: true
    console.log(myString.includes("Universe")); // 输出: false

看到了吗?只需要一行代码,就能轻松完成开头、结尾和包含的判断,简直不要太爽!

三、参数详解:不仅仅是查找那么简单

这三个方法都接收一些可选参数,让你的查找更加灵活。

  • startsWith(searchString, position)

    • searchString: 要查找的子字符串。
    • position (可选): 从字符串的哪个位置开始查找。 默认为 0。
    const myString = "Hello World!";
    
    console.log(myString.startsWith("World", 6)); // 输出: true (从索引 6 开始查找)
    console.log(myString.startsWith("Hello", 6)); // 输出: false (从索引 6 开始查找)
  • endsWith(searchString, length)

    • searchString: 要查找的子字符串。
    • length (可选): 将字符串视为从头开始,长度为length的字符串,然后判断该字符串是否以searchString结尾。默认为字符串的长度。
    const myString = "Hello World!";
    
    console.log(myString.endsWith("Hello", 5)); // 输出: true (将 "Hello" 视为整个字符串)
    console.log(myString.endsWith("World", 5)); // 输出: false (将 "Hello" 视为整个字符串)
  • includes(searchString, position)

    • searchString: 要查找的子字符串。
    • position (可选): 从字符串的哪个位置开始查找。 默认为 0。
    const myString = "Hello World!";
    
    console.log(myString.includes("World", 7)); // 输出: false (从索引 7 开始查找)
    console.log(myString.includes("o", 5));   // 输出: true (从索引 5 开始查找)

四、应用场景:从实际出发

这三个方法在实际开发中有很多应用场景。

  1. 文件类型判断:

    const filename = "image.png";
    
    if (filename.endsWith(".png")) {
      console.log("这是一个 PNG 图片");
    } else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
      console.log("这是一个 JPG 图片");
    } else {
      console.log("未知文件类型");
    }
  2. URL 路由:

    const url = "/api/users/123";
    
    if (url.startsWith("/api/users")) {
      console.log("这是一个用户相关的 API");
    }
  3. 数据验证:

    const phoneNumber = "13812345678";
    
    if (phoneNumber.startsWith("13") && phoneNumber.length === 11) {
      console.log("这是一个有效的手机号码");
    }
  4. 关键词高亮:

    const text = "This is a sample text with some keywords.";
    const keyword = "keyword";
    
    if (text.includes(keyword)) {
      const highlightedText = text.replace(keyword, `<span style="background-color: yellow">${keyword}</span>`);
      console.log(highlightedText);
      //输出:This is a sample text with some <span style="background-color: yellow">keyword</span>s.
    }
  5. 日志分析:

    const logMessage = "[ERROR] Something went wrong!";
    
    if (logMessage.startsWith("[ERROR]")) {
      console.log("这是一个错误日志");
    } else if (logMessage.startsWith("[WARNING]")) {
      console.log("这是一个警告日志");
    }

五、性能考量:别过分担心

有人可能会担心这些方法的性能问题。 实际上,现代 JavaScript 引擎对这些方法进行了优化,性能通常不会成为瓶颈。

如果你需要进行大量的字符串查找操作,可以考虑使用正则表达式,或者使用一些专门的字符串搜索算法。但在大多数情况下,startsWith()endsWith()includes() 已经足够满足你的需求了。

六、兼容性问题:老版本浏览器怎么办?

startsWith()endsWith()includes() 是 ES6 引入的方法,在一些老版本的浏览器中可能不支持。

如果你需要兼容老版本的浏览器,可以使用 polyfill 来解决这个问题。 Polyfill 是一段代码,它提供了老版本浏览器不支持的新特性。

下面是一个简单的 startsWith() polyfill:

if (!String.prototype.startsWith) {
  String.prototype.startsWith = function(searchString, position) {
    position = position || 0;
    return this.substr(position, searchString.length) === searchString;
  };
}

endsWith()includes() 也可以使用类似的 polyfill 方法。

七、和正则表达式的比较:各有千秋

正则表达式是强大的字符串匹配工具,可以实现复杂的模式匹配。 但对于简单的开头、结尾和包含判断,startsWith()endsWith()includes() 更加简洁易懂。

特性 startsWith()/endsWith()/includes() 正则表达式
易用性 简单易懂,容易上手 学习曲线陡峭,需要掌握正则表达式语法
性能 通常性能较好,适合简单查找 对于复杂模式匹配,性能更优
灵活性 只能进行简单的开头、结尾和包含判断 可以实现复杂的模式匹配,例如模糊匹配、范围匹配等
代码可读性 代码简洁,可读性高 正则表达式复杂时,可读性较差

举个例子:

startsWith() 判断字符串是否以 "abc" 开头:

const myString = "abcdefg";
console.log(myString.startsWith("abc")); // 输出: true

用正则表达式判断字符串是否以 "abc" 开头:

const myString = "abcdefg";
const regex = /^abc/;
console.log(regex.test(myString)); // 输出: true

可以看到,对于简单的开头判断,startsWith() 的代码更加简洁易懂。

总结:

startsWith()endsWith()includes() 是 JavaScript 中非常实用的字符串查找方法,它们让代码更加简洁易懂,提高了开发效率。 它们就像是字符串界的瑞士军刀,虽然功能不多,但足够应对日常的字符串处理任务。 在实际开发中,根据具体的需求选择合适的方法,才能更好地提高代码质量和开发效率。

好了,今天的分享就到这里。 希望大家下次在字符串查找的时候,能够想起这些小助手,让你的代码更加优雅、高效! 感谢大家的聆听! 如果有什么问题,欢迎提问。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注