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:
- Call ToString, giving it the this value as its argument.
- Call ToInteger(start).
- If length is undefined, use +∞; otherwise call ToInteger(length).
- Compute the number of characters in Result(1).
- If Result(2) is positive or zero, use Result(2); else use max(Result(4)+Result(2),0).
- Compute min(max(Result(3),0), Result(4)–Result(5)).
- If Result(6) ≤ 0, return the empty String “”.
- 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:
- Call CheckObjectCoercible passing the this value as its argument.
- Let S be the result of calling ToString, giving it the this value as its argument.
- Let len be the number of characters in S.
- Let intStart be ToInteger(start).
- If end is undefined, let intEnd be len; else let intEnd be ToInteger(end).
- Let finalStart be min(max(intStart, 0), len).
- Let finalEnd be min(max(intEnd, 0), len).
- Let from be min(finalStart, finalEnd).
- Let to be max(finalStart, finalEnd).
- 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.