最快的解决方案?
我运行了一些基准测试,此解决方案获得了巨大的成功: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
或RegExp
的其他解决方案对性能造成了很大的影响,但速度却慢了两个数量级。使用join
上的结果split
,当然,增加了一个额外的性能损失。
他们为什么慢一些?每当必须创建新对象或数组时,JS都必须从OS请求大块内存。这个过程很慢。
如果您正在追逐基准测试,则以下是一些一般准则:
- 为对象
{}
或数组[]
(如split
创建的对象)分配新的动态内存会花费很多性能。
RegExp
搜索比字符串搜索更为复杂,因此速度较慢。
- 如果已经有一个数组,则对数组进行解构的速度与显式索引它们的速度差不多,并且看起来很棒。
超出首次实例
这是一个解决方案,可分割并包括第n个实例。它的速度不尽如人意,但是在OP的问题上,gobble(element, '_', 1)
它仍然比a 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中运行的。