【问题标题】:How to check if a string "StartsWith" another string?如何检查一个字符串“StartsWith”是否是另一个字符串?
【发布时间】:2010-10-13 09:30:11
【问题描述】:

如何在 JavaScript 中编写相当于 C# 的 String.StartsWith

var haystack = 'hello world';
var needle = 'he';

haystack.startsWith(needle) == true

注意:这是一个老问题,正如 cmets ECMAScript 2015 (ES6) 中指出的那样,引入了.startsWith 方法。但是,在撰写此更新 (2015) browser support is far from complete.

【问题讨论】:

    标签: javascript string startswith


    【解决方案1】:

    您可以使用 ECMAScript 6 的 String.prototype.startsWith() 方法,但它是 not yet supported in all browsers。您需要使用 shim/polyfill 将其添加到不支持它的浏览器上。创建一个符合all the details laid out in the spec 的实现有点复杂。如果您想要一个忠实的垫片,请使用:

    一旦你填充了这个方法(或者如果你只支持已经拥有它的浏览器和 JavaScript 引擎),你可以像这样使用它:

       console.log("Hello World!".startsWith("He")); // true
        
    var haystack = "Hello world";
    var prefix = 'orl';
    console.log(haystack.startsWith(prefix)); // false

    【讨论】:

    • 警告!这些 jsperf 测试不适用于擅长 JIT 编译的浏览器。 Firefox 和 Chrome 等浏览器有时会在操作结果被丢弃时识别它,因此不会执行该操作。除此之外,现代 javascript 引擎使用 分支预测,因此每次迭代中的测试字符串应该不同。
    • 注意:如果 typescript 在尝试构建项目时抱怨,您至少需要在 tsconfig.json 的 lib 数组中包含“es2015.core”
    【解决方案2】:

    字符串对象有startsWith、endsWith和includes方法。

    • StartsWith 检查给定的字符串是否从开头开始。

    • endsWith 检查给定的字符串是否在末尾。

    • includes 检查给定的字符串是否存在于任何部分。

    您可以在下面的 youtube 视频中找到这三者之间的完全区别

    https://www.youtube.com/watch?v=E-hyeSwg0PA

    【讨论】:

      【解决方案3】:

      最佳解决方案:

      function startsWith(str, word) {
          return str.lastIndexOf(word, 0) === 0;
      }
      

      如果你也需要,这里是 endsWith

      function endsWith(str, word) {
          return str.indexOf(word, str.length - word.length) !== -1;
      }
      

      对于那些喜欢将其原型化为字符串的人:

      String.prototype.startsWith || (String.prototype.startsWith = function(word) {
          return this.lastIndexOf(word, 0) === 0;
      });
      
      String.prototype.endsWith   || (String.prototype.endsWith = function(word) {
          return this.indexOf(word, this.length - word.length) !== -1;
      });
      

      用法:

      "abc".startsWith("ab")
      true
      "c".ensdWith("c") 
      true
      

      使用方法:

      startsWith("aaa", "a")
      true
      startsWith("aaa", "ab")
      false
      startsWith("abc", "abc")
      true
      startsWith("abc", "c")
      false
      startsWith("abc", "a")
      true
      startsWith("abc", "ba")
      false
      startsWith("abc", "ab")
      true
      

      【讨论】:

      • 我认为你在函数中混淆了 lastIndexOf 和 indexOf - startsWith 应该是 return str.indexOf(word, 0) === 0;
      • @RichardMatheson 使用 indexOf 的问题是,如果它在开始时匹配失败,它将继续搜索整个字符串,其中 lastIndexOf 从单词的长度开始并返回到零。明白了吗?
      • 啊,是的,现在说得通了——我没有注意你使用的索引。非常好的技巧!
      【解决方案4】:
      1. 这个问题有点老了,但我想写这个答案是为了向你展示我根据这里提供的所有答案和 Jim Buck 分享的 jsperf 所做的一些基准测试。

      我基本上需要一种快速的方法来确定一根长针是否在大海捞针中,它们非常相似,除了最后一个字符。

      这是我为每个函数(拼接、子字符串、startsWith 等)编写的代码,测试它们在返回 false 和 true 时针对 1.000.0001 个字符的 haystack 字符串 (nestedString) 和一个虚假或真实1.000.000 个字符的针串(分别为testParentStringFalsetestParentStringTrue):

      // nestedString is made of 1.000.001 '1' repeated characters.
      var nestedString = '...'
      
      // testParentStringFalse is made of 1.000.000 characters,
      // all characters are repeated '1', but the last one is '2',
      // so for this string the test should return false.
      var testParentStringFalse = '...'
      
      // testParentStringTrue is made of 1.000.000 '1' repeated characters,
      // so for this string the test should return true.
      var testParentStringTrue = '...'
      
      // You can make these very long strings by running the following bash command
      // and edit each one as needed in your editor
      // (NOTE: on OS X, `pbcopy` copies the string to the clipboard buffer,
      //        on Linux, you would probably need to replace it with `xclip`):
      // 
      //     printf '1%.0s' {1..1000000} | pbcopy
      // 
      
      function testString() {
          let dateStart
          let dateEnd
          let avg
          let count = 100000
          const falseResults = []
          const trueResults = []
      
          /* slice */
          console.log('========> slice')
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.slice(0, testParentStringFalse.length) === testParentStringFalse
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          falseResults[falseResults.length] = {
              label: 'slice',
              avg
          }
          console.log(`testString() slice = false`, res, 'avg: ' + avg + 'ms')
      
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.slice(0, testParentStringTrue.length) === testParentStringTrue
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          trueResults[trueResults.length] = {
              label: 'slice',
              avg
          }
          console.log(`testString() slice = true`, res, 'avg: ' + avg + 'ms')
          console.log('<======== slice')
          console.log('')
          /* slice END */
      
          /* lastIndexOf */
          console.log('========> lastIndexOf')
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.lastIndexOf(testParentStringFalse, 0) === 0
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          falseResults[falseResults.length] = {
              label: 'lastIndexOf',
              avg
          }
          console.log(`testString() lastIndexOf = false`, res, 'avg: ' + avg + 'ms')
      
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.lastIndexOf(testParentStringTrue, 0) === 0
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          trueResults[trueResults.length] = {
              label: 'lastIndexOf',
              avg
          }
          console.log(`testString() lastIndexOf = true`, res, 'avg: ' + avg + 'ms')
          console.log('<======== lastIndexOf')
          console.log('')
          /* lastIndexOf END */
      
          /* indexOf */
          console.log('========> indexOf')
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.indexOf(testParentStringFalse) === 0
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          falseResults[falseResults.length] = {
              label: 'indexOf',
              avg
          }
          console.log(`testString() indexOf = false`, res, 'avg: ' + avg + 'ms')
      
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.indexOf(testParentStringTrue) === 0
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          trueResults[trueResults.length] = {
              label: 'indexOf',
              avg
          }
          console.log(`testString() indexOf = true`, res, 'avg: ' + avg + 'ms')
          console.log('<======== indexOf')
          console.log('')
          /* indexOf END */
      
          /* substring */
          console.log('========> substring')
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.substring(0, testParentStringFalse.length) === testParentStringFalse
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          falseResults[falseResults.length] = {
              label: 'substring',
              avg
          }
          console.log(`testString() substring = false`, res, 'avg: ' + avg + 'ms')
      
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.substring(0, testParentStringTrue.length) === testParentStringTrue
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          trueResults[trueResults.length] = {
              label: 'substring',
              avg
          }
          console.log(`testString() substring = true`, res, 'avg: ' + avg + 'ms')
          console.log('<======== substring')
          console.log('')
          /* substring END */
      
          /* startsWith */
          console.log('========> startsWith')
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.startsWith(testParentStringFalse)
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          falseResults[falseResults.length] = {
              label: 'startsWith',
              avg
          }
          console.log(`testString() startsWith = false`, res, 'avg: ' + avg + 'ms')
      
          dateStart = +new Date()
          var res
          for (let j = 0; j < count; j++) {
              res = nestedString.startsWith(testParentStringTrue)
          }
          dateEnd = +new Date()
          avg = (dateEnd - dateStart)/count
          trueResults[trueResults.length] = {
              label: 'startsWith',
              avg
          }
          console.log(`testString() startsWith = true`, res, 'avg: ' + avg + 'ms')
          console.log('<======== startsWith')
          console.log('')
          /* startsWith END */
      
          falseResults.sort((a, b) => a.avg - b.avg)
          trueResults.sort((a, b) => a.avg - b.avg)
      
          console.log('false results from fastest to slowest avg:', falseResults)
          console.log('true results from fastest to slowest avg:', trueResults)
      }
      
      

      我在 Chrome 75Firefox 67Safari 12Opera 62 上运行了这个基准测试。

      我没有包含 Edge 和 IE,因为我在这台机器上没有它们,但是如果你们中的某个人想要针对 Edge 和至少 IE 9 运行脚本并在此处分享输出,我会非常好奇地看到结果。

      请记住,您需要重新创建 3 个长字符串并将脚本保存在一个文件中,然后在浏览器中打开该文件,因为在浏览器控制台上复制/粘贴会阻止它,因为每个字符串的长度 >= 1.000.000) .

      这里是输出:

      Chrome 75(substring 获胜):

      false results from fastest to slowest avg:
      1)  {"label":"substring","avg":0.08271}
      2)  {"label":"slice","avg":0.08615}
      3)  {"label":"lastIndexOf","avg":0.77025}
      4)  {"label":"indexOf","avg":1.64375}
      5)  {"label":"startsWith","avg":3.5454}
      
      true results from fastest to slowest avg:
      1)  {"label":"substring","avg":0.08213}
      2)  {"label":"slice","avg":0.08342}
      3)  {"label":"lastIndexOf","avg":0.7831}
      4)  {"label":"indexOf","avg":0.88988}
      5)  {"label":"startsWith","avg":3.55448}
      

      Firefox 67(indexOf 获胜):

      false results from fastest to slowest avg
      1)  {"label":"indexOf","avg":0.1807}
      2)  {"label":"startsWith","avg":0.74621}
      3)  {"label":"substring","avg":0.74898}
      4)  {"label":"slice","avg":0.78584}
      5)  {"label":"lastIndexOf","avg":0.79668}
      
      true results from fastest to slowest avg:
      1)  {"label":"indexOf","avg":0.09528}
      2)  {"label":"substring","avg":0.75468}
      3)  {"label":"startsWith","avg":0.76717}
      4)  {"label":"slice","avg":0.77222}
      5)  {"label":"lastIndexOf","avg":0.80527}
      

      Safari 12(slice 赢得虚假结果,startsWith 赢得真实结果,而且 Safari 在执行整个测试的总时间方面是最快的):

      false results from fastest to slowest avg:
      1) "{\"label\":\"slice\",\"avg\":0.0362}"
      2) "{\"label\":\"startsWith\",\"avg\":0.1141}"
      3) "{\"label\":\"lastIndexOf\",\"avg\":0.11512}"
      4) "{\"label\":\"substring\",\"avg\":0.14751}"
      5) "{\"label\":\"indexOf\",\"avg\":0.23109}"
      
      true results from fastest to slowest avg:
      1) "{\"label\":\"startsWith\",\"avg\":0.11207}"
      2) "{\"label\":\"lastIndexOf\",\"avg\":0.12196}"
      3) "{\"label\":\"substring\",\"avg\":0.12495}"
      4) "{\"label\":\"indexOf\",\"avg\":0.33667}"
      5) "{\"label\":\"slice\",\"avg\":0.49923}"
      

      Opera 62(substring 获胜。结果与 Chrome 相似,我并不感到惊讶,因为 Opera 基于 Chromium 和 Blink):

      false results from fastest to slowest avg:
      {"label":"substring","avg":0.09321}
      {"label":"slice","avg":0.09463}
      {"label":"lastIndexOf","avg":0.95347}
      {"label":"indexOf","avg":1.6337}
      {"label":"startsWith","avg":3.61454}
      
      true results from fastest to slowest avg:
      1)  {"label":"substring","avg":0.08855}
      2)  {"label":"slice","avg":0.12227}
      3)  {"label":"indexOf","avg":0.79914}
      4)  {"label":"lastIndexOf","avg":1.05086}
      5)  {"label":"startsWith","avg":3.70808}
      

      事实证明,每个浏览器都有自己的实现细节(除了基于 Chrome 的 Chromium 和 Blink 的 Opera)。

      当然,可以而且应该使用不同的用例进行进一步测试(例如,当针与干草堆相比真的很短时,当干草堆比针短时等等......),但在我的情况下,我需要比较长字符串,想在这里分享。

      【讨论】:

        【解决方案5】:

        我不确定 javascript 但在打字稿中我做了类似的事情

        var str = "something";
        (<String>str).startsWith("some");
        

        我想它也应该适用于 js。 希望对你有帮助!

        【讨论】:

          【解决方案6】:

          如果您使用的是startsWith()endsWith(),那么您必须注意前导空格。这是一个完整的例子:

          var str1 = " Your String Value Here.!! "; // Starts & ends with spaces    
          if (str1.startsWith("Your")) { }  // returns FALSE due to the leading spaces…
          if (str1.endsWith("Here.!!")) { } // returns FALSE due to trailing spaces…
          
          var str2 = str1.trim(); // Removes all spaces (and other white-space) from start and end of `str1`.
          if (str2.startsWith("Your")) { }  // returns TRUE
          if (str2.endsWith("Here.!!")) { } // returns TRUE
          

          【讨论】:

          • 这是非常不标准的行为:字符串“abc”不以“abc”开头。更具体地说,ECMA 6 不假设任何类型的字符串修剪,因此空格必须完全匹配才能产生 startsWith 匹配。
          • 什么...这是如何回答问题的?
          • @DCShannon 不是。这是令人费解的废话。
          • @SteveHollasch 我的目的是让任何人都在寻找我面临的相同问题。在使用startsWith()endsWith() 函数时,我们需要注意前导空格。没有别的!
          【解决方案7】:

          由于这很受欢迎,我认为值得指出的是,在 ECMA 6 中有此方法的实现,并且为此应该使用“官方”polyfill 以防止将来出现问题和撕裂。

          p>

          幸运的是,Mozilla 的专家为我们提供了一个:

          https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith

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

          请注意,这具有在过渡到 ECMA 6 时被优雅地忽略的优势。

          【讨论】:

            【解决方案8】:

            我只是想补充一下我对此的看法。

            我认为我们可以这样使用:

            var haystack = 'hello world';
            var needle = 'he';
            
            if (haystack.indexOf(needle) == 0) {
              // Code if string starts with this substring
            }
            

            【讨论】:

            • @relfor 比较了 Mark Byers 答案的三种不同正确方法的性能。这种正确的方法并不受欢迎,因为它需要搜索整个字符串。
            • @maxpolk 我认为indexOf 在第一次出现时会停止搜索整个字符串。我已经检查过了。
            • 如果一开始没有找到第一个匹配项,那么这种方法会随着继续寻找它的时间越长而变得低效,可能会一直搜索到最后,而不是更早地放弃。由于存在效率低下的可能性,因此在三种正确方法中不受欢迎。
            • @Mr.D 如果没有匹配?
            • 当所有的草垛都被搜索到了?更好:stackoverflow.com/a/36876507/961018 .. 只搜索字长
            【解决方案9】:

            这是对 CMS 解决方案的一个小改进:

            if(!String.prototype.startsWith){
                String.prototype.startsWith = function (str) {
                    return !this.indexOf(str);
                }
            }
            
            "Hello World!".startsWith("He"); // true
            
             var data = "Hello world";
             var input = 'He';
             data.startsWith(input); // true
            

            检查该函数是否已经存在,以防将来的浏览器以本机代码实现它,或者它是否由另一个库实现。例如,原型库已经实现了这个功能。

            使用!=== 0 略快且简洁,但可读性较差。

            【讨论】:

            • 这可能会成为一个问题:如果已经实施的实现与我自己的行为不同,这会破坏我的应用程序。
            • 使用!那里很乱
            • -1;将此添加到String.prototype 是一个坏主意,因为它与specString.prototype.startsWith 完全不符。如果您这样做,任何尝试使用 ES6 方法的代码都可能会失败;它可能会查看该方法是否已定义,查看它是否已定义(很糟糕,由您定义)并且没有添加符合规范的 shim,从而导致以后出现错误行为。
            【解决方案10】:

            没有辅助函数,只使用正则表达式的.test 方法:

            /^He/.test('Hello world')
            

            使用动态字符串而不是硬编码的字符串来做到这一点(假设字符串不包含任何正则表达式控制字符):

            new RegExp('^' + needle).test(haystack)
            

            你应该检查Is there a RegExp.escape function in Javascript?是否存在正则表达式控制字符出现在字符串中的可能性。

            【讨论】:

            • 为了使表达式区分大小写,使用/^he/i
            【解决方案11】:

            最佳的性能解决方案是停止使用库调用,而只是认识到您正在使用两个数组。与我在这里看到的所有其他解决方案相比,手动实现既短又快。

            function startsWith2(str, prefix) {
                if (str.length < prefix.length)
                    return false;
                for (var i = prefix.length - 1; (i >= 0) && (str[i] === prefix[i]); --i)
                    continue;
                return i < 0;
            }
            

            有关性能比较(成功和失败),请参阅http://jsperf.com/startswith2/4。 (确保您检查可能胜过我的更高版本。)

            【讨论】:

              【解决方案12】:

              .lastIndexOf 的另一种选择:

              haystack.lastIndexOf(needle, 0) === 0
              

              haystack 的索引0 开始,通过haystack 向后查找needle。换句话说,它只检查haystack 是否以needle 开头。

              原则上,这应该比其他一些方法具有性能优势:

              • 它不会搜索整个haystack
              • 它不会创建一个新的临时字符串然后立即丢弃它。

              【讨论】:

              • 不确定@rfcoder89 正在处理哪种情况 - jsfiddle.net/jkzjw3w2/1
              • @rfcoder89 注意lastIndexOf的第二个参数:"aba".lastIndexOf ("a")正如你所指出的那样是2,但"aba".lastIndexOf ("a", 0)是0,这是正确的
              • 非常感谢。 String.startsWith 在 Android lollipop WebView 上不起作用,但是这个 lastIndexOf sn-p 可以!!!
              • lastIndexOf 字符串从结尾搜索到开头,因此它搜索整个字符串:因此它的效率低下对于非常长的字符串进行搜索。
              • @willywonka 不,如果你有 0 startIndex,它不是从 0 pos 开始搜索的,它是唯一的检查。仅当 fromIndex >= str.length 时才搜索整个字符串。
              【解决方案13】:

              我最近问过自己同样的问题。
              有多种可能的解决方案,这里有 3 个有效的解决方案:

              • s.indexOf(starter) === 0
              • s.substr(0,starter.length) === starter
              • s.lastIndexOf(starter, 0) === 0(在看到 Mark Byers 的 answer 后添加)
              • 使用循环:

                function startsWith(s,starter) {
                  for (var i = 0,cur_c; i < starter.length; i++) {
                    cur_c = starter[i];
                    if (s[i] !== starter[i]) {
                      return false;
                    }
                  }
                  return true;
                }
                

              我还没有遇到最后一个使用循环的解决方案。
              令人惊讶的是,此解决方案的性能明显优于前 3 个。
              这是我为得出这个结论而执行的 jsperf 测试:http://jsperf.com/startswith2/2

              和平

              ps:ecmascript 6 (harmony) 为字符串引入了原生 startsWith 方法。
              试想一下,如果他们考虑在初始版本中包含这个急需的方法,将会节省多少时间。

              更新

              正如史蒂夫指出的(关于这个答案的第一条评论),如果给定的 prefix 比整个字符串短,上述自定义函数将引发错误。他已经修复了这个问题并添加了一个循环优化,可以在 http://jsperf.com/startswith2/4 上查看。

              请注意,Steve 包含了 2 个循环优化,其中第一个表现出更好的性能,因此我将在下面发布该代码:

              function startsWith2(str, prefix) {
                if (str.length < prefix.length)
                  return false;
                for (var i = prefix.length - 1; (i >= 0) && (str[i] === prefix[i]); --i)
                  continue;
                return i < 0;
              }
              

              【讨论】:

              【解决方案14】:

              根据这里的答案,这是我现在正在使用的版本,因为它似乎提供了基于 JSPerf 测试的最佳性能(据我所知,它在功能上是完整的)。

              if(typeof String.prototype.startsWith != 'function'){
                  String.prototype.startsWith = function(str){
                      if(str == null) return false;
                      var i = str.length;
                      if(this.length < i) return false;
                      for(--i; (i >= 0) && (this[i] === str[i]); --i) continue;
                      return i < 0;
                  }
              }
              

              这是基于以下位置的 startsWith2:http://jsperf.com/startswith2/6。我为微小的性能改进添加了一个小调整,此后还添加了对比较字符串是否为空或未定义的检查,并使用 CMS 的答案中的技术将其转换为添加到字符串原型。

              请注意,此实现不支持此 Mozilla Developer Network 页面中提到的“位置”参数,但这似乎不是 ECMAScript 提案的一部分。

              【讨论】:

                【解决方案15】:

                我刚刚了解了这个字符串库:

                http://stringjs.com/

                包含 js 文件,然后像这样使用S 变量:

                S('hi there').endsWith('hi there')
                

                也可以通过安装在NodeJS中使用:

                npm install string
                

                然后要求它作为S 变量:

                var S = require('string');
                

                如果您不喜欢这个,该网页还包含指向备用字符串库的链接。

                【讨论】:

                  【解决方案16】:

                  还可以查看underscore.string.js。它带有一堆有用的字符串测试和操作方法,包括startsWith 方法。来自文档:

                  startsWith _.startsWith(string, starts)

                  该方法检查string是否以starts开头。

                  _("image.gif").startsWith("image")
                  => true
                  

                  【讨论】:

                  • 我需要_.string.startsWith
                  【解决方案17】:

                  您还可以通过为数组原型创建自己的原型/扩展来返回以字符串开头的数组的所有成员,也就是

                  Array.prototype.mySearch = function (target) {
                      if (typeof String.prototype.startsWith != 'function') {
                          String.prototype.startsWith = function (str){
                          return this.slice(0, str.length) == str;
                        };
                      }
                      var retValues = [];
                      for (var i = 0; i < this.length; i++) {
                          if (this[i].startsWith(target)) { retValues.push(this[i]); }
                      }
                      return retValues;
                  };
                  

                  并使用它:

                  var myArray = ['Hello', 'Helium', 'Hideout', 'Hamster'];
                  var myResult = myArray.mySearch('Hel');
                  // result -> Hello, Helium
                  

                  【讨论】:

                    【解决方案18】:
                    var str = 'hol';
                    var data = 'hola mundo';
                    if (data.length >= str.length && data.substring(0, str.length) == str)
                        return true;
                    else
                        return false;
                    

                    【讨论】:

                      【解决方案19】:
                      data.substring(0, input.length) === input
                      

                      【讨论】:

                      • @ANeves 我怀疑这在很大程度上取决于浏览器和使用的数据。请参阅 Ben Weaver 的实际测量答案。在我当前正在运行的浏览器上(Windows 上的 Chrome 12.0.742)子字符串获胜,准备好的正则表达式获胜。
                      • @cobbal 也许吧。但是.lastIndexOf(input, 0) 比较前 N 个字符,而.substring(0, input.length) === input 计算 N 个,将数据子串化为 N 个长度,然后比较这 N 个字符。除非有代码优化,否则第二个版本不能比另一个更快。不过不要误会我的意思,我自己永远找不到比你建议的更好的东西。 :)
                      • @ANeves 但是将返回 false 的长字符串上的 .lastIndexOf 将迭代整个字符串 (O(N)),而 .substring 情况下迭代可能要小得多的字符串。如果您期望大多数成功或只有少量输入,则 .lastIndexOf 可能更快 - 否则 .substring 可能更快。如果输入比被检查的字符串长,.substring 也会有异常的风险。
                      • @ChrisMoschini,不要忘记 Mark Byers 的解决方案有 lastIndexOf 从索引 0 开始,而不是结束。最初,这也让我感到困惑。尽管如此,检查字符串以什么开头是一项非常常见的任务,以至于 JavaScript 确实应该为它提供适当的 API,而不是您在此页面上看到的所有习语和替代方法,无论它们多么聪明。
                      • 我更喜欢 cobbal 的解决方案而不是 Mark 的解决方案。即使标记更快,并且使用参数的技巧令人印象深刻,但与子字符串相比,它也很难阅读。
                      猜你喜欢
                      • 2022-03-31
                      • 2013-05-12
                      • 2019-05-11
                      • 2021-05-06
                      • 1970-01-01
                      • 2013-03-13
                      相关资源
                      最近更新 更多