我该如何在JavaScript中编写与C#的String.StartsWith
功能相同的代码?
var haystack = 'hello world';
var needle = 'he';
haystack.startsWith(needle) == true
注意:这是一个旧问题,正如评论中指出的那样,ECMAScript 2015(ES6)引入了 .startsWith
方法。然而,在撰写本次更新(2015年)时,浏览器支持还远未完整。
我该如何在JavaScript中编写与C#的String.StartsWith
功能相同的代码?
var haystack = 'hello world';
var needle = 'he';
haystack.startsWith(needle) == true
注意:这是一个旧问题,正如评论中指出的那样,ECMAScript 2015(ES6)引入了 .startsWith
方法。然而,在撰写本次更新(2015年)时,浏览器支持还远未完整。
String.prototype.startsWith()
方法。它已经得到了所有主流浏览器的支持。但是,如果您想在不支持该方法的浏览器中使用它,则需要使用一个 shim/polyfill 在这些浏览器上添加它。创建一个符合规范中的所有细节的实现有点复杂。如果您想要一个忠实的 shim,请使用以下之一:
String.prototype.startsWith
shim, 或者String.prototype.startsWith
。一旦您使用 shim(或者仅支持已经拥有该方法的浏览器和 JavaScript 引擎),您可以像这样使用它:
console.log("Hello World!".startsWith("He")); // true
var haystack = "Hello world";
var prefix = 'orl';
console.log(haystack.startsWith(prefix)); // false
使用.lastIndexOf
的另一种替代方法:
haystack.lastIndexOf(needle) === 0
该方法从字符串haystack
的长度开始向后检查needle
的出现情况,直到第0个索引位置。换句话说,它只检查haystack
是否以needle
开头。
lastIndexOf
方法提供了一个可选参数'fromIndex'。如果给定,则向后搜索从此给定的索引位置开始,并向后遍历到索引零。但我们必须不指定任何除最后一个索引之外的fromIndex,否则搜索可能会忽略某些内容。
原则上,该方法应比某些其他方法具有性能优势:
haystack
。data.substring(0, input.length) === input
.lastIndexOf(input, 0)
只比较前N个字符,而.substring(0, input.length) === input
会计算N的值,将数据切割成N长度的子串,然后再比较这N个字符。除非代码进行了优化,否则第二种方法不能比第一种更快。不过别误解,我自己也不可能想出比你建议的更好的方法。 :) - ANeveslastIndexOf
从索引0开始计算,而不是从结尾开始计算。这也曾经让我困扰过。尽管有各种巧妙的方法和替代方案,但检查一个字符串以什么开头还是一个很常见的任务,JavaScript应该有一个合适的API来完成它。 - Randall Cook不使用帮助函数,只使用正则表达式的.test
方法:
/^He/.test('Hello world')
如果要使用动态字符串而不是硬编码的字符串来实现这一点(假设该字符串不包含任何正则表达式控制字符):
new RegExp('^' + needle).test(haystack)
如果在字符串中可能出现正则表达式控制字符,那么你应该查看JavaScript 中是否有 RegExp.escape 函数?
/^he/i
。 - kaizer1v最佳解决方案:
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
我只是想表达一下我的观点。
我认为我们可以这样使用:
var haystack = 'hello world';
var needle = 'he';
if (haystack.indexOf(needle) == 0) {
// Code if string starts with this substring
}
indexOf
会在找到第一个匹配项后停止搜索整个字符串。我已经验证过了。 - Mr.D这里是对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
检查函数是否已存在,以防将来的浏览器在本地代码中实现它或者由另一个库实现。例如,Prototype库已经实现了这个函数。
使用!
比=== 0
稍微快一些,更加简洁,但不太易读。
String.prototype
是一个坏主意,因为它与String.prototype.startsWith
的规范几乎没有任何关系。如果您这样做,任何试图使用ES6方法的代码都有可能失败;它可能会查看该方法是否已经定义,看到它已经被您糟糕地定义了,而不添加符合规范的shim,从而导致以后的行为不正确。 - Mark Amery还可以查看underscore.string.js。 它附带了许多有用的字符串测试和操作方法,包括一个startsWith
方法。 从文档中了解:
startsWith
_.startsWith(string, starts)
该方法检查
string
是否以starts
开头。
_("image.gif").startsWith("image") => true
_.string.startsWith
。 - Colonel Panic我最近也问了自己同样的问题。
有多种可能的解决方案,以下是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(harmony)为字符串引入了一个本地startsWith
方法。
如果他们在初始版本中想到包含这个非常需要的方法,将节省多少时间。
更新
正如史蒂夫在本答案的第一条评论中指出的那样,上面的自定义函数会抛出错误,如果给定的prefix短于整个字符串。他已经修复了这个问题,并添加了一个循环优化,可以在http://jsperf.com/startswith2/4中查看。
请注意,史蒂夫包括了两个循环优化,其中第一个表现更好,因此我将在下面发布该代码:
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中有这种方法的实现,为了避免未来出现问题和泪水,应该使用“官方”的polyfill。
幸运的是,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时会被优雅地忽略。