为什么在历史上' substring '已经存在时要添加' substr '
Why historically was `substr` added when `substring` already existed?
我知道substr(start[, length])
和substring(start[, end])
之间的区别。这在前面的问题中得到了解决:substr和substring之间的区别是什么?
但是为什么在substring
已经存在的情况下才添加substr
?我想知道这个决定的历史。
我发现substring
从一开始就在那里,然后"突然"在Ecmascript第三版中,他们有两个不同的函数来用不同的参数实现完全相同的事情。为什么?
如果没有十年前参与ECMA的人参与,我认为我们不能明确地回答这个问题,但我们可以推断出一些事情。
substring
请求从0开始的索引,也可以选择从0开始的索引。
substr
请求起始点的索引(从0开始)和长度。这使得它在某些情况下更容易使用,例如,如果你想从第一个"s"中获取2个字符,你可以指定2作为长度,而不是必须首先计算第一个"s"的索引,然后加上2,然后将两个位置传递给substring
。
正如在评论中指出的,substr
允许负起始位置。
substr
是一个更好的实现。所以这很可能就是为什么它被添加。
至于为什么两者都在那里的问题,这可能是为了向后兼容。因为Javascript运行在各种各样的浏览器中(现在也运行在其他地方),在由多个组织维护的运行时中,没有简单的方法来弃用或消除任何东西。更简单的做法是把它留在那里,然后添加更多的内容到语言中。旧代码仍然可以工作,新代码有更好的选项可供使用。
这两个函数的用例是不同的。
String.prototype.substr()
允许您使用负起始值从字符串的末尾获取子字符串,这使得它适合于一些更多的用例,而不会生成过于冗长,不可读的代码。
// alert('1234567890'.substring('1234567890'.length - 4)) <-- UGLY
alert('1234567890'.substr(-4))
仅凭这一点,它就使得问题中函数实现完全相同的事情的假设完全错误,这与问为什么存在任何其他函数没有什么不同。唯一能回答这个问题的人就是做这个决定的人。
正如所说,它们并不相同,它们只是可以做一些共同的操作。事实上,他们完成工作的内部步骤也各不相同。以下是Ecma International网站上的一些引用:
B.2.3 String.prototype.substr (start, length) substr方法接受两个参数,start和length,并返回a将this对象转换为String对象的结果的子字符串;从字符位置开始并运行长度(如果长度为undefined,则通过字符串的末尾)。如果start为负,则将其处理为(sourceLength+start),其中sourceLength是字符串的长度。结果是一个String值,而不是字符串对象。执行以下步骤:substr方法的length属性为2。
- 调用ToString,给它这个值作为参数。
- 调用ToInteger (开始)。
- 如果长度定义,使用+∞;否则调用ToInteger(length)。
- 计算结果(1)中的字符数
- 如果Result(2)为正或为零,则使用Result(2);
使用max(Result(4)+Result(2),0)。- 计算最小(最大(结果(3),0),结果(4)结果(5))。
- 如果结果(6)≤0,返回空字符串" "
- 返回一个字符串,包含Result(1)中的6个连续字符,以位置Result(5)的字符开始。
注意:substr函数故意是通用的;它不要求它的this值是String对象。因此它可以是传递给其他类型的对象作为方法使用。
和
15.5.4.15 String.prototype.substring (start, end)
子字符串方法接受两个参数,start和end,并返回a将此对象转换为字符串的结果的子字符串,从字符位置开始运行到,但不是包括字符位置,结束的字符串(或通过的结束end is undefined)。结果是一个String值,而不是字符串对象。如果参数为NaN或负值,则将其替换为零;如果任何一个参数都大于String的长度,是的
如果start大于end,它们被交换。
执行以下步骤:
子字符串方法的length属性为2。
- 调用CheckObjectCoercible,传递this值作为参数。
- 让S是调用ToString的结果,给它这个值作为参数。
- 让len为s中的字符数。
- 让intStart为ToInteger(start)。
- 如果end未定义,则设置 intent 为len;else let intent be ToInteger(end).
- 让 finalStart 是min (max ( intStart 0), len )。
- 让 finalEnd 是min (max (意愿 0), len )。
- 让是最小值( finalStart , finalEnd )。
- 让 max ( finalStart , finalEnd )。
- 返回一个长度从到 - 的String,包含S中的字符,即从到到−1的下标字符,按升序排列。
注意:子字符串函数故意是通用的;事实并非如此要求它的this值是String对象。因此,它可以是传递给其他类型的对象作为方法使用。
所以底线是它们不是相同的方法,它们的用法也不相同。
substr
允许从末尾提取子字符串,如:"Good news, everyone!".substr(-4);
将返回one!
。(IE8不支持)。由于JavaScript不支持函数重载。所以我的理论是,这个从末尾提取子字符串的功能是社区非常需要的,因此他们引入了类似的功能,只是有一点变化。我不知道真正的原因是什么,但据我所知,缺乏对函数重载的原生支持可能导致了这个substr
函数的诞生。
为什么?因为方便。
大概。如果不询问这个决定的原作者,就没有办法知道确切的答案。
但是我们只能假设它是基于类似于导致在Visual Basic中具有例如函数Left
和Right
的推理,即使使用具有不同参数组合的Mid
函数可以获得相同的结果,尽管不太方便并且需要更多或更长的代码行。(或者,用自己喜欢的语言找个比喻)
substr
的length
参数代替substring
的end
参数可以获得一些轻微的可读性/简洁性增益:
var test = "First Second Last";
//If you want "Second", do either of:
alert(test.substring(test.indexOf("Second"), test.indexOf("Second") + 'Second'.length))
alert(test.substr(test.indexOf("Second"), "Second".length)) //<------ WOW!! ---------->
或者,当使用substring
时,您可以将test.indexOf("Second")
存储在一个临时变量中以缩短substring
调用:
var n = test.indexOf("Second");
alert(test.substring(n, n + 'Second'.length))
,但这是多一行代码和一个额外的温度,你不需要使用substr
。
- 正在添加'X'按钮,在文本字段旁边使用javascript
- 如何在映射数组中添加换行符
- 正在将数据主题添加到所有项目
- ZeroClipboard-在复制之前添加到值
- 我可以在json对象中添加一个函数吗
- 将输入字段中的文本提交到我的数据库,同时将其添加到我的列表中
- 正在SharePoint 2013母版页中添加JQuery移动文件
- 如何添加浮动和非浮动,其他
- 添加文字和评论功能更新Div
- 如果使用 lodash 将属性存在于另一个对象中,则向对象添加属性
- 动态地改变“”的URL;添加新项目”;链接使用javascript/jquery
- 在函数中添加数组元素的数值
- 如何将歌曲添加到jPlayer
- 在html Select中添加搜索
- Java脚本时间添加
- FabricJs-限制主对象内添加对象的移动区域
- JQuery添加元素需要在我的js之前再次添加JQuery脚本
- 如何在Google柱状图中动态添加行/列
- 正在尝试使用if和else添加类,但无法正常工作
- 为什么在历史上' substring '已经存在时要添加' substr '