当`substring`已经存在时,为什么历史上会添加`substr`?

时间:2015-09-20 13:05:42

标签: javascript

我知道substr(start[, length])substring(start[, end])之间的区别。例如,这可以解决在之前的问题中:What is the difference between substr and substring?

但是为什么他们在substr已经存在后会添加substring?我正在寻找有关此决定历史的信息。

我发现substring从一开始就存在,然后突然出现了#39}。在Ecmascript第3版中,他们有两个不同的函数来实现具有不同参数的完全相同的东西。为什么呢?

4 个答案:

答案 0 :(得分:7)

2个功能的用例不同。

String.prototype.substr()允许您使用负起始值从字符串末尾获取子字符串,这使得它适用于更多用例而不会生成过于冗长,不可读的代码。

// alert('1234567890'.substring('1234567890'.length - 4)) <-- UGLY
alert('1234567890'.substr(-4))

仅凭这一点,它在问题中假设函数完全完全相同的事情完全错误,并且这使得它没有什么不同,然后询问为什么存在任何其他函数。能够回答这个问题的唯一人就是做出这个决定的人。

答案 1 :(得分:5)

我认为,如果没有十年前与ECMA有关的人权衡,我们不能明确地回答这个问题,但我们可以推断一些事情。

substring要求开头的索引(从0开始),并且可选地要求结束的索引(从0开始)。

substr询问开头的索引(从0开始)和长度。这使得在某些情况下使用起来更简单,例如如果你想从第一个“s”中获取2个字符,你可以只指定2作为长度,而不必首先计算第一个“s”的索引然后再加2,然后将两个位置传递给{{ 1}}。

正如评论中指出的那样,substring允许负起始位置。

可以说,substr是一个更好的实现。所以这很可能是它被添加的原因。

关于为什么两者都存在的问题,这可能是为了向后兼容。因为Javascript在各种浏览器中运行(现在在其他地方运行),在由多个组织维护的运行时中,没有简单的方法来弃用或消除任何东西。只需将其留在那里并添加更多语言就可以了。旧代码仍然有效,新代码可以使用更好的选项。

答案 2 :(得分:2)

据说,他们不一样,他们只是可以做一些共同的操作。事实上,他们完成工作的内部步骤也各不相同。以下是Ecma International网站的一些引用:

  

B.2.3 String.prototype.substr(start,length)

     

substr 方法有两个参数, start length ,并返回一个   将此对象转换为String的结果的子字符串,   从字符位置开始开始并运行 length   字符(如果长度 未定义,则通过字符串的结尾)。   如果 start 为负数,则将其视为( sourceLength + start )其中    sourceLength 是String的长度。结果是一个字符串   value,而不是String对象。采取以下步骤:

     
      
  1. 调用ToString,将 this 值作为其参数。
  2.   
  3. 致电ToInteger(开始)。
  4.   
  5. 如果长度 未定义,请使用+∞;否则请调用ToInteger( length )。
  6.   
  7. 计算结果(1)中的字符数。
  8.   
  9. 如果结果(2)为正或零,则使用结果(2);否则使用max(Result(4)+ Result(2),0)。
  10.   
  11. 计算min(max(结果(3),0),结果(4)-Result(5))。
  12.   
  13. 如果Result(6)≤0,则返回空字符串“”。
  14.   
  15. 返回一个字符串,其中包含Result(1)中Result(6)个连续字符,从位置Result(5)处的字符开始。
  16.         

    substr 方法的长度属性 2

         

    注意: substr 功能是故意通用的;它不需要   它的 this 值是一个String对象。因此它可以   转移到其他类型的对象用作方法。

  

15.5.4.15 String.prototype.substring(start,end)

     

substring 方法有两个参数, start end ,并返回一个   将此对象转换为String的结果的子字符串,   从角色位置开始开始并运行到,但不是   包括字符串的字符位置 end (或通过结束   String end 未定义)。结果是String值,而不是a   字符串对象。

     

如果任一参数为 NaN 或为负数,则将其替换为零;如果   两个参数都大于String的长度,它是   替换为String的长度。

     

如果 start 大于 end ,则会交换它们。

     

采取以下步骤:

     
      
  1. 调用CheckObjectCoercible,将 this 值作为参数传递。
  2.   
  3. 设S是调用ToString的结果,给它 this 值作为参数。
  4.   
  5. len 为S中的字符数。
  6.   
  7. intStart 成为ToInteger( start )。
  8.   
  9. 如果 end 未定义,请将 intEnd 设为len;否则让 intEnd 成为ToInteger( end )。
  10.   
  11. finalStart 为min(max( intStart ,0), len )。
  12.   
  13. finalEnd 为min(max( intEnd ,0), len )。
  14.   
  15. 分钟( finalStart finalEnd )。
  16.   
  17. 为max( finalStart finalEnd )。
  18.   
  19. 将长度为的字符串从返回到 - ,其中包含S中的字符,即索引的字符 -1,按升序排列。
  20.         

    子串方法的长度属性 2

         

    注意:子串函数是有意通用的;它不是   要求其 this 值为String对象。因此,它可以   转移到其他类型的对象用作方法。

因此,底线既不是相同的方法,也不是它们的用法相同。

答案 3 :(得分:-1)

substr允许从最后提取子字符串,如:"Good news, everyone!".substr(-4);将返回one!。 (不支持IE8-)。由于 JavaScript本身不支持函数重载。所以我的理论是,从末端开始提取子字符串的这一特征在很大程度上受到了社区的要求,因此他们引入了与另一个名称相似的功能并略有变化。我不知道究竟是什么原因,但据我所知,缺少对函数重载的原生支持可能会导致这个substr函数的诞生。