elclanrs 和 raina77ow 似乎只在 cmets 中解决了很多困惑,所以让我发布一个澄清的答案。
澄清
来自“string.splice”的人可能会期待它,就像数组中的那个:
- 最多接受 3 个参数:起始位置、长度和(可选)插入(字符串)
- 退回剪切部分
- 修改原字符串
问题是,由于字符串是不可变的(相关:1,2),无法满足 3d 要求,我找到了最专业的评论 here:
在 JavaScript 中,字符串是原始值类型,不是对象 (spec)。事实上,在 ES5 中,它们是与 null、undefined、number 和 boolean 并列的仅有的 5 种值类型之一。字符串由 value 和 not 通过引用分配,并按原样传递。因此,字符串不仅是不可变的,它们还是一个值。将字符串 "hello" 更改为 "world" 就像决定从现在开始数字 3 就是数字 4……这没有任何意义。
因此,考虑到这一点,人们可能只期望“string.splice”这个东西:
- 最多接受 2 个参数:起始位置、长度(插入没有意义,因为字符串没有改变)
- 退回剪切部分
这就是substr 所做的;或者,或者,
- 最多接受 3 个参数:起始位置、长度和(可选)插入(字符串)
- 返回修改后的字符串(不带剪切部分,带插入)
这是下一节的主题。
解决方案
如果您关心优化,您可能应该使用 Mike 的实现:
String.prototype.splice = function(index, count, add) {
if (index < 0) {
index += this.length;
if (index < 0)
index = 0;
}
return this.slice(0, index) + (add || "") + this.slice(index + count);
}
不过,处理越界索引可能会有所不同。根据您的需要,您可能需要:
if (index < 0) {
index += this.length;
if (index < 0)
index = 0;
}
if (index >= this.length) {
index -= this.length;
if (index >= this.length)
index = this.length - 1;
}
甚至
index = index % this.length;
if (index < 0)
index = this.length + index;
如果您不关心性能,您可能需要调整 Kumar 的建议,该建议更直接:
String.prototype.splice = function(index, count, add) {
var chars = this.split('');
chars.splice(index, count, add);
return chars.join('');
}
性能
随着琴弦长度的增加,性能上的差异会急剧增加。 jsperf shows,对于长度为 10 的字符串,后一种解决方案(拆分和连接)比前一种解决方案(使用切片)慢两倍,对于 100 个字母的字符串,它是 x5,对于 1000 个字母的字符串,它是 x50,在Ops/sec 它是:
10 letters 100 letters 1000 letters
slice implementation 1.25 M 2.00 M 1.91 M
split implementation 0.63 M 0.22 M 0.04 M
请注意,当从 10 个字母移动到 100 个字母时,我已经更改了 1st 和 2d 参数(但我仍然对 100 个字母的测试比 10 个字母的测试运行得更快感到惊讶)。