为什么子字符串不处理负索引?

12

substr() 可以完美地处理负索引,但 substring() 仅接受非负索引。

是否有不使用 substr 而选择 substring 的原因?在许多情况下,通过将索引空间视为循环群来使用负索引非常有用。为什么 MDN 标记 substr 为“已弃用”?


5
substr和substring是JavaScript中用于截取字符串的两种方法。它们有点不同,但都可以用于截断一个字符串并返回子字符串。substr()使用起始位置和要提取的字符数来指定要提取的子串。例如,str.substr(2, 4)将从字符串str的第三个字符开始提取四个字符。substring()使用起始和结束位置来指定要提取的子串。例如,str.substring(2, 6)将从字符串str的第三个字符开始提取到第七个字符(不包括第七个字符)。需要注意的是,如果第二个参数为负数,则substr()将其视为将字符串末尾减去该值;而substring()将其视为0。 - j08691
1
@j08691 那篇帖子中有解释为什么substring()不接受负索引吗?我找不到。 - showdev
1
@showdev 这并不是他的问题。他只是指出了这一点,但他的问题是“为什么不使用substr而选择substring?”在j08691发布的链接中,有人提到substring优于所有其他替代方案。关于为什么substr被“弃用”,我认为这仅仅是因为substring是一个更好的性能替代品。 - Tyler Roper
2
@TylerRoper 我看到的问题是:“为什么子字符串不处理负索引?”,“有没有不使用substr而使用substring的原因?”,“为什么MDN标记substr为‘已弃用’?”在我看来,解释这两个函数之间的区别并不能真正回答这些问题。但也许这些答案太基于个人观点了。 - showdev
1
@TylerRoper 这是帖子的标题。无论如何,我并不担心它。我只是好奇。 - showdev
显示剩余2条评论
3个回答

7

当你想要指定起始和结束索引时,使用substring。当你想要指定起始偏移量和长度时,使用substr。它们执行不同的操作并具有不同的用例。

编辑: 为了更好地回答确切的问题:
为什么substring不能处理负索引?

substring 指定字符串中字符的起始和结束 索引substr 处理起始 偏移量 和长度。对我来说,substring 不允许负索引是有道理的,因为实际上不存在负索引(字符串中的字符从0到n进行索引,“负索引”将超出范围)。由于 substr 处理的是 偏移量 而不是 索引,我认为偏移量这个术语足够宽松,可以允许负偏移量,这当然意味着从字符串末尾向后计数而不是从开头向前计数。这可能只是语义学上的问题,但这就是我理解的方式。

为什么 substr 被弃用了?

我认为它实际上没有被弃用。

修订历史记录显示MDN substr的弃用通知是基于以下博客文章发布的:

2016年8月16日上午12:00:34 hexalys 根据https://blog.whatwg.org/javascript添加了弃用说明

该文章指出HTML字符串方法已被弃用(应该是这样)。这些方法将字符串包装在HTML标记中,例如"abc".sub() 将返回 <sub>abc</sub>。该博客文章列出了所有HTML字符串方法,但在我看来,错误地将subtr列为HTML字符串方法(实际上并不是)。

所以我认为这是一个误解。

(下面是摘录,我加了重点)

亮点:

臭名昭著的“字符串HTML方法”:String.prototype.anchor(name)、String.prototype.big()、String.prototype.blink()、 String.prototype.bold()、String.prototype.fixed()、 String.prototype.fontcolor(color)、String.prototype.fontsize(size)、 String.prototype.italics()、String.prototype.link(href)、 String.prototype.small()、String.prototype.strike()、 String.prototype.sub()、String.prototype.substr(start, length)和 String.prototype.sup()。浏览器以各种略有不同的方式实现了这些方法,其中一种情况导致了安全问题(不仅仅是理论上的!)。这是一个艰苦的斗争,但最终浏览器和ECMAScript规范匹配了JavaScript标准所定义的行为。

https://blog.whatwg.org/javascript


2
额外的证据:这是ES2015规范条目 ,指出当ECMAScript主机是Web浏览器时它是“必需的。[substr]具有规范性,但如果ECMAScript主机不是Web浏览器,则是可选的。”还有一个在ES2015规范中的条目 - Mike Cluck

3

在JS中有三个函数几乎执行相同的功能:

  • substring
  • substr
  • slice

我猜大部分人使用最后一个,因为它与其对应的数组操作相匹配。前两个则是历史遗留问题(substring从JS1开始,然后出现了两种不同的substr等)。

为什么MDN标记substr为“废弃”?

这是基于此篇文章的内容,由Mathias添加的通知,其中substr被列在“字符串HTML方法”下。废弃的原因是它属于Annex B,该规范说明如下:

本附录描述了基于Web浏览器的ECMAScript实现的各种旧特性和其他特征。在没有旧代码使用的情况下,本规范中指定的所有语言特性和行为都具有一个或多个不良特征,并且将被移除。


1
它已经被整个语言废弃,但在浏览器环境中实际上是必需的。 "当ECMAScript主机是Web浏览器时,此附录中定义的ECMAScript语言语法和语义是必需的。" [来源](http://www.ecma-international.org/ecma-262/6.0/#sec-additional-ecmascript-features-for-web-browsers) - Mike Cluck
@MikeC:只需要支持旧版本即可,不应在新代码中使用。 - georg
我并不反对。我只是在说它在技术上被定义和指定为浏览器使用。 - Mike Cluck

3

substr函数在处理未知长度的字符串时非常有用,特别是当你只关心字符串末尾的N个字符时。

例如,如果你想知道一个字符串是否以单个字符结尾:

function endsWith(str, character) {
  return str.substr(-1) === character;
}

endsWith('my sentence.', '.'); // => true
endsWith('my other sentence', '.'); // => false

使用 substring 实现相同的功能需要您先计算字符串的长度。

function endsWith(str, character) {
  var length = str.length;
  return str.substring(length - 1, length) === character;
}

这两个函数都可以用来获得相同的结果,但使用 substr 更加方便。


我不确定这如何回答任何已发布的问题。我有什么遗漏吗?“为什么substring不能处理负索引?”,“是否有不使用substr而使用substring的原因?”,“为什么MDN标记substr为'已弃用'?” - showdev
我试图通过区分它们来回答“为什么使用X而不是Y”的问题。我没有涵盖的另一个区别是,substring使用索引作为最后一个参数而不是长度,如果您已经在处理字符串的索引,则特别有用。 - Steven Schobert
@showdev 我同意你上面的评论,这种问题主要是基于个人观点的,所以也许我的回答不太合适。 - Steven Schobert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接