The only real difference between the two is that substr() is non-standard1, while substring() are standard built-in functions, ignoring differences when the starting index is not 0.
slice() is also very similar, but allows negative end indices (number from end, which substring() does not allow).
1:substr() is not officially standard, though pretty much all browsers support it. For compatibility reasons, the standardising committee provides a "recommended" way of implementing this non-standard function, but it's not part of the official standard.