Non-regex解决方案
我运行了一些基准测试,这个解决方案获得了巨大的成功
str.slice(str.indexOf(delim) + delim.length)
// as function
function gobbleStart(str, delim) {
return str.slice(str.indexOf(delim) + delim.length);
}
// as polyfill
String.prototype.gobbleStart = function(delim) {
return this.slice(this.indexOf(delim) + delim.length);
};
与其他解决方案的性能比较
唯一接近的竞争者是同一行代码,除了使用substr而不是slice。
我尝试的其他解决方案,包括拆分或regexp,性能受到了很大的影响,大约慢了2个数量级。当然,在拆分结果上使用join会增加额外的性能损失。
为什么它们变慢了?每当需要创建一个新对象或数组时,JS都必须向操作系统请求一大块内存。这个过程非常缓慢。
以下是一些通用指南,以防你在追逐基准测试:
为对象{}或数组[]分配新的动态内存(就像split所创建的那样)将在性能上付出很大的代价。
RegExp搜索更复杂,因此比字符串搜索慢。
如果你已经有一个数组,解构数组和显式索引数组一样快,而且看起来很棒。
从第一个实例移除
下面是一个解决方案,它将分割到并包括第n个实例。它没有那么快,但在OP的问题上,gobble(element, '_', 1)仍然比RegExp或split解决方案快>2倍,并且可以做更多:
/*
`gobble`, given a positive, non-zero `limit`, deletes
characters from the beginning of `haystack` until `needle` has
been encountered and deleted `limit` times or no more instances
of `needle` exist; then it returns what remains. If `limit` is
zero or negative, delete from the beginning only until `-(limit)`
occurrences or less of `needle` remain.
*/
function gobble(haystack, needle, limit = 0) {
let remain = limit;
if (limit <= 0) { // set remain to count of delim - num to leave
let i = 0;
while (i < haystack.length) {
const found = haystack.indexOf(needle, i);
if (found === -1) {
break;
}
remain++;
i = found + needle.length;
}
}
let i = 0;
while (remain > 0) {
const found = haystack.indexOf(needle, i);
if (found === -1) {
break;
}
remain--;
i = found + needle.length;
}
return haystack.slice(i);
}
根据上面的定义,gobble('path/to/file.txt', '/')将给出文件的名称,而gobble('prefix_category_item', '_', 1)将像这个答案中的第一个解决方案一样删除前缀。
测试在macOSX 10.14上的Chrome 70.0.3538.110中运行。