非正则表达式解决方案
我跑了一些benchmarks,这个解决方案大获全胜:1
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。
我尝试过的涉及 split 或 RegExps 的其他解决方案对性能造成了很大影响,并且速度慢了大约 2 个数量级。在split 的结果上使用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 中运行的。