patternjavascriptMajor
Check whether string ends with string
Viewed 0 times
withendscheckwhetherstring
Problem
I wrote the following to check whether a string ends with a second string.
Usage:
This takes a substring with the size of the target string counting from the end of the string and checks whether it's equal to the target string. Quite straightforward. However, I'm concerned about my usage of
Is there a more idiomatic approach for writing such a basic function? Would slicing be more appropriate? The naming can probably be improved.
function isEndOf(origin, target) {
return (origin.substr(target.length * -1, target.length) === target);
}Usage:
isEndOf("A long time ago in a galaxy far, far away", "far away")This takes a substring with the size of the target string counting from the end of the string and checks whether it's equal to the target string. Quite straightforward. However, I'm concerned about my usage of
target.length * -1. This smells like using the wrong method altogether.Is there a more idiomatic approach for writing such a basic function? Would slicing be more appropriate? The naming can probably be improved.
Solution
There's no need for the 2nd argument in
or
Same deal.
Edit: Whoops. Actually it's not quite the same deal. As Sumurai8 commented on Simon's answer, MDN says that JScript does not handle negative offsets for
Instead of
One thing you might want, though, is to check
One gotcha though: It'll return false if
And you might want to check
So to check
By the way, without the
Origin Target Result
==========================================
"foo" "" false
"" "foo" false
"" "" true
Results #2 makes sense, but results #1 and #3 are perhaps a little strange, because, again, what does it mean to have an string end with an empty string? The results are due to
Kinda confusing.
If you want an empty target string to always return true, you could do:
I'm aware my code has a lot of white-space for JavaScript standards. I like to think it keeps code readable. The naming can probably be improved.
Whitespace seems just fine to me! Don't know what JS you're used to, but I see absolutely no reason to change anything about whitespace usage.
I would drop the outer parentheses though, like Simon suggested.
As for naming, I'd call it
You could also extend the
Here we can skip checking
substr. So you could just do:origin.substr(target.length * -1) === targetor
origin.slice(target.length * -1) === targetSame deal.
Edit: Whoops. Actually it's not quite the same deal. As Sumurai8 commented on Simon's answer, MDN says that JScript does not handle negative offsets for
substr. However, slice has no such caveat. So long story short: Use slice, not substr.Instead of
* -1, you could also use a unary minus:origin.slice(-target.length) === targetOne thing you might want, though, is to check
target before you try accessing its length property. If target == undefined you'll get an error. Something simple like this should do:if(!target) return false;One gotcha though: It'll return false if
target is an empty string, since empty strings are false'y. However, it doesn't really make much sense to check if string ends with an empty string, so perhaps that's fine? Otherwise, do a typeof check (like the one below) on target.And you might want to check
origin too. However, here you just want to check that it's a string - not if it's just false'y. You'll be calling slice on it, so it must be a string or you'll get an error, whereas the worst that can happen if target isn't a string (but is truth'y) is that target.length is undefined.So to check
origin do:if(typeof origin !== 'string') return false;By the way, without the
target-is-false'y check, if target is a string but also empty, you'll get some tricky results:Origin Target Result
==========================================
"foo" "" false
"" "foo" false
"" "" true
Results #2 makes sense, but results #1 and #3 are perhaps a little strange, because, again, what does it mean to have an string end with an empty string? The results are due to
slice(-0) being the same as slice(0), i.e. returning the whole string. So in effect you're checking:"foo".slice(0) == "" // => "foo" == "" (false)
"".slice(0) == "" // => "" == "" (true)Kinda confusing.
If you want an empty target string to always return true, you could do:
if(typeof origin !== 'string') return false;
if(typeof target !== 'string') return false;
if(!target) return true;I'm aware my code has a lot of white-space for JavaScript standards. I like to think it keeps code readable. The naming can probably be improved.
Whitespace seems just fine to me! Don't know what JS you're used to, but I see absolutely no reason to change anything about whitespace usage.
I would drop the outer parentheses though, like Simon suggested.
As for naming, I'd call it
endsWith, or stringEndsWith.You could also extend the
String prototype with an endsWith method, but generally it's better to leave native prototypes alone. However, this is fairly harmless, so I'd be tempted to say:if(!String.prototype.endsWith) {
String.prototype.endsWith = function (ending) {
if(typeof ending !== 'string') return false;
if(!ending) return true;
return this.slice(-ending.length) === ending;
};
}Here we can skip checking
origin, because we're adding the method to String itself. So if it's called, it's called on a string.Code Snippets
origin.substr(target.length * -1) === targetorigin.slice(target.length * -1) === targetorigin.slice(-target.length) === targetif(!target) return false;if(typeof origin !== 'string') return false;Context
StackExchange Code Review Q#115125, answer score: 24
Revisions (0)
No revisions yet.