Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why historically was `substr` added when `substring` already existed? [closed]

Tags:

javascript

I know what the difference is between substr(start[, length]) and substring(start[, end]). This is addressed e.g. in this earlier question: What is the difference between substr and substring?

But why did they add substr later when substring was already present? I am looking for information about the history of this decision.

I have found that substring was there from the beginning and then 'suddenly' in Ecmascript 3rd edition they have two different functions to achieve the exact same thing with different arguments. Why?

like image 249
David Mulder Avatar asked Sep 20 '15 13:09

David Mulder


3 Answers

I don't think we can definitively answer this without someone involved with ECMA ten years ago weighing in, however we can infer some things.

substring asks for the index (from 0) of the start, and optionally an index (again from 0) of the end.

substr asks for the index (from 0) of the start, and a length. That makes it simpler to use for some cases, e.g. if you want to fetch 2 characters from the first "s" you can just specify 2 as the length instead of having to first calculate the index of the first "s" and then adding 2 to that, and then passing both positions to substring.

As was pointed out in a comment, substr allows a negative starting position.

Arguably, substr is a better implementation. And so that is quite possibly why it was added.

As to the question of why are both there, that is probably for backward compatibility. Because Javascript runs in a wide variety of browsers (and these days elsewhere), in runtimes maintained by multiple organizations, there is no easy way to deprecate or eliminate anything. It's easier to just leave it there and add more to the language instead. Old code still works, and new code has better options available to use.

like image 25
Dan Lowe Avatar answered Oct 26 '22 20:10

Dan Lowe


Use cases for the 2 functions are different.

String.prototype.substr() lets you take a substring from the end of the string using negative start value which makes it suitable for some more use cases without generating overly verbose, unreadable code.

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

By that alone it makes the assumption in the question that the functions achieve the exact same thing simply wrong, and that makes it no different then asking why any other function exist. The only people who can answer such a question are the ones who made that decision.

like image 74
Amit Avatar answered Oct 26 '22 20:10

Amit


As told, they are not the same, they just can do some operations in common. In fact, their internal steps to complete the work are also different from each other. Here are some quotes from Ecma International's site:

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

The substr method takes two arguments, start and length, and returns a substring of the result of converting the this object to a String, starting from character position start and running for length characters (or through the end of the String if length is undefined). If start is negative, it is treated as (sourceLength+start) where sourceLength is the length of the String. The result is a String value, not a String object. The following steps are taken:

  1. Call ToString, giving it the this value as its argument.
  2. Call ToInteger(start).
  3. If length is undefined, use +∞; otherwise call ToInteger(length).
  4. Compute the number of characters in Result(1).
  5. If Result(2) is positive or zero, use Result(2); else use max(Result(4)+Result(2),0).
  6. Compute min(max(Result(3),0), Result(4)–Result(5)).
  7. If Result(6) ≤ 0, return the empty String “”.
  8. Return a String containing Result(6) consecutive characters from Result(1) beginning with the character at position Result(5).

The length property of the substr method is 2.

NOTE: The substr function is intentionally generic; it does not require that its this value be a String object. Therefore it can be transferred to other kinds of objects for use as a method.

and

15.5.4.15 String.prototype.substring (start, end)

The substring method takes two arguments, start and end, and returns a substring of the result of converting this object to a String, starting from character position start and running to, but not including, character position end of the String (or through the end of the String is end is undefined). The result is a String value, not a String object.

If either argument is NaN or negative, it is replaced with zero; if either argument is larger than the length of the String, it is replaced with the length of the String.

If start is larger than end, they are swapped.

The following steps are taken:

  1. Call CheckObjectCoercible passing the this value as its argument.
  2. Let S be the result of calling ToString, giving it the this value as its argument.
  3. Let len be the number of characters in S.
  4. Let intStart be ToInteger(start).
  5. If end is undefined, let intEnd be len; else let intEnd be ToInteger(end).
  6. Let finalStart be min(max(intStart, 0), len).
  7. Let finalEnd be min(max(intEnd, 0), len).
  8. Let from be min(finalStart, finalEnd).
  9. Let to be max(finalStart, finalEnd).
  10. Return a String whose length is to - from, containing characters from S, namely the characters with indices from through to −1, in ascending order.

The length property of the substring method is 2.

NOTE: The substring function is intentionally generic; it does not require that its this value be a String object. Therefore, it can be transferred to other kinds of objects for use as a method.

So bottom line is neither they are the same methods, nor their usages are the same.

like image 38
Gökay Gürcan Avatar answered Oct 26 '22 22:10

Gökay Gürcan