如何检查字符串 “StartsWith” 是否为另一个字符串?

如何在 JavaScript 中编写等效于 C#的String.StartsWith

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

haystack.startsWith(needle) == true

注意:这是一个古老的问题,正如注释中指出的那样,ECMAScript 2015(ES6)引入了.startsWith方法。但是,在撰写此更新(2015)时, 浏览器支持还远远没有完成

答案

您可以使用 ECMAScript 6 的String.prototype.startsWith()方法,但并非所有浏览器都支持该方法 。您将需要使用填充程序 / 填充来将其添加到不支持它的浏览器中。创建一个符合规范中所有细节的实现会有些复杂。如果您想要忠实的垫片,请使用以下任一方法:

对方法进行填充后(或者如果您仅支持已拥有该方法的浏览器和 JavaScript 引擎),则可以按以下方式使用它:

"Hello World!".startsWith("He"); // true

var haystack = "Hello world";
var prefix = 'orl';
haystack.startsWith(prefix); // false

.lastIndexOf另一种选择:

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

这看起来向后通过haystack对于发生needle从指数开始0haystack 。换句话说,它仅检查haystack是否以needle开始。

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

  • 它不会搜索整个haystack
  • 它不会创建新的临时字符串,然后立即将其丢弃。
data.substring(0, input.length) === input

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

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

为此,请使用动态字符串而不是硬编码的字符串(假设该字符串将不包含任何正则表达式控制字符):

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

您应该检查一下Java 中是否存在 RegExp.escape 函数?如果有可能在字符串中出现正则表达式控制字符。

最佳解决方案:

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

用过的:

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

如果您也需要endsWith

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

对于那些喜欢将其原型化为 String 的用户:

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

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

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

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

if (haystack.indexOf(needle) == 0) {
  // Code if string starts with this substring
}

这是 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更快,更简洁。

还要查看underscore.string.js 。它带有许多有用的字符串测试和操作方法,包括startsWith方法。从文档:

startsWith _.startsWith(string, starts)

此方法检查string是否以starts

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

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

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

    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;
    }

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

和平

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

更新资料

正如 Steve 指出的那样(此答案的第一条评论),如果给定的前缀短于整个字符串,则上述自定义函数将引发错误。他已修复该问题,并添加了循环优化功能,可以在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;
}

由于这种方法非常流行,因此我认为值得指出的是,ECMA 6 中有此方法的一种实现,并且为防止将来出现问题和撕裂,应该使用 “官方” 填充料。

幸运的是,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 时会被忽略。