Related
I need to fetch particular function and its body as a text from the javascript file and print that function as an output using C#. I need to give function name and js file as an input parameter. I tried using regex but couldnt achieved the desired result. Here is the code of regex.
public void getFunction(string jstext, string functionname)
{
Regex regex = new Regex(#"function\s+" + functionname + #"\s*\(.*\)\s*\{");
Match match = regex.Match(jstext);
}
Is there any other way I can do this?
This answer is based on the assumption which you provide in comments, that the C# function needs only to find function declarations, and not any form of function expressions.
As I point out in comments, javascript is too complex to be efficiently expressed in a regular expression. The only way to know you've reached the end of the function is when the brackets all match up, and given that, you still need to take escape characters, comments, and strings into account.
The only way I can think of to achieve this, is to actually iterate through every single character, from the start of your function body, until the brackets match up, and keep track of anything odd that comes along.
Such a solution is never going to be very pretty. I've pieced together an example of how it might work, but knowing how javascript is riddled with little quirks and pitfalls, I am convinced there are many corner cases not considered here. I'm also sure it could be made a bit tidier.
From my first experiments, the following should handle escape characters, multi- and single line comments, strings that are delimited by ", ' or `, and regular expressions (i.e. delimited by /).
This should get you pretty far, although I'm intrigued to see what exceptions people can come up with in comments:
private static string GetFunction(string jstext, string functionname) {
var start = Regex.Match(jstext, #"function\s+" + functionname + #"\s*\([^)]*\)\s*{");
if(!start.Success) {
throw new Exception("Function not found: " + functionname);
}
StringBuilder sb = new StringBuilder(start.Value);
jstext = jstext.Substring(start.Index + start.Value.Length);
var brackets = 1;
var i = 0;
var delimiters = "`/'\"";
string currentDelimiter = null;
var isEscape = false;
var isComment = false;
var isMultilineComment = false;
while(brackets > 0 && i < jstext.Length) {
var c = jstext[i].ToString();
var wasEscape = isEscape;
if(isComment || !isEscape)
{
if(c == #"\") {
// Found escape symbol.
isEscape = true;
} else if(i > 0 && !isComment && (c == "*" || c == "/") && jstext[i-1] == '/') {
// Found start of a comment block
isComment = true;
isMultilineComment = c == "*";
} else if(c == "\n" && isComment && !isMultilineComment) {
// Found termination of singline line comment
isComment = false;
} else if(isMultilineComment && c == "/" && jstext[i-1] == '*') {
// Found termination of multiline comment
isComment = false;
isMultilineComment = false;
} else if(delimiters.Contains(c)) {
// Found a string or regex delimiter
currentDelimiter = (currentDelimiter == c) ? null : currentDelimiter ?? c;
}
// The current symbol doesn't appear to be commented out, escaped or in a string
// If it is a bracket, we should treat it as one
if(currentDelimiter == null && !isComment) {
if(c == "{") {
brackets++;
}
if(c == "}") {
brackets--;
}
}
}
sb.Append(c);
i++;
if(wasEscape) isEscape = false;
}
return sb.ToString();
}
Demo
In javascript:
"Id".localeCompare("id")
will report that "id" is bigger. I want to do ordinal (not locale) compare such that "Id" is bigger. This is similar to String.CompareOrdinal in C#. How can I do it?
I support the answers given by Raymond Chen and pst. I will back them up with documentation from my favorite site for answers to JavaScript questions -- The Mozilla Developer Network. As an aside, I would highly recommend this site for any future JavaScript questions you may have.
Now, if you go to the MDN section entitled String, under the section "Comparing strings", you will find this description:
C developers have the strcmp() function for comparing strings. In JavaScript, you just use the less-than and greater-than operators:
var a = "a";
var b = "b";
if (a < b) // true
print(a + " is less than " + b);
else if (a > b)
print(a + " is greater than " + b);
else
print(a + " and " + b + " are equal.");
A similar result can be achieved using the localeCompare method inherited by String instances.
If we were to use the string "Id" for a and "id" for b then we would get the following result:
"Id is less than id"
This is the same result that Yaron got earlier when using the localeCompare method. As noted in MDN, using the less-than and greater-than operators yields similar results as using localeCompare.
Therefore, the answer to Yaron's question is to use the less-than (<) and greater-than (>) operators to do an ordinal comparison of strings in JavaScript.
Since Yaron mentioned the C# method String.CompareOrdinal, I would like to point out that this method produces exactly the same results as the above JavaScript. According to the MSDN C# documentation, the String.CompareOrdinal(String, String) method "Compares two specified String objects by evaluating the numeric values of the corresponding Char objects in each string." So the two String parameters are compared using the numeric (ASCII) values of the individual characters.
If we use the original example by Yaron Naveh in C#, we have:
int result = String.CompareOrdinal("Id", "id");
The value of result is an int that is less than zero, and is probably -32 because the difference between "I" (0x49) and "i" (0x69) is -0x20 = -32. So, lexically "Id" is less than "id", which is the same result we got earlier.
As Raymond noted (and explained) in a comment, an "ordinal" non-locale aware compare is as simple as using the various equality operators on strings (just make sure both operands are strings):
"a" > "b" // false
"b" > "a" // true
To get a little fancy (or don't muck with [[prototype]], the function is the same):
String.prototype.compare = function (a, b) {
return ((a == b ? 0)
? (a > b : 1)
: -1)
}
Then:
"a".compare("b") // -1
Happy coding.
Just a guess: by inverting case on all letters?
function compareOrdinal(ori,des){
for(var index=0;index<ori.length&&index<des.length;index++){
if(des[index].charCodeAt(0)<ori[index].charCodeAt(0)){
return -1;
break;
}
}
if(parseInt(index)===des.length-1){
return 0;
}
return 1;
}
compareOrdinal("idd","id");//output 1
if you need to compare and find difference between two string, please check this:
function findMissingString() {
var str1 = arguments[0];
var str2 = arguments[1];
var i = 0 ;
var j = 0 ;
var text = '' ;
while(i != (str1.length >= str2.length ? str1.length : str2.length )) {
if(str1.charAt(i) == str2.charAt(j)) {
i+=1 ;
j+=1;
} else {
var indexing = (str1.length >= str2.length ? str1.charAt(i) : str2.charAt(j));
text = text + indexing ;
i+=1;
j+=1;
}
}
console.log("From Text = " + text);
}
findMissingString("Hello","Hello world");
This question already has answers here:
How can I do string interpolation in JavaScript?
(21 answers)
Closed 8 years ago.
i am tired of writing this:
string_needed="prefix....." + topic + "suffix...." + name + "testing";
i would think someone might have done something about this by now ;)
ES6 Update:
ES6 added template strings, which use backticks (`) instead of single or double quotes. In a template string, you can use the ${} syntax to add expressions. Using your example, it would be:
string_needed = `prefix.....${topic}suffix....${name}testing`
Original answer:
Sorry :(
I like to take advantage of Array.join:
["prefix ....", topic, "suffix....", name, "testing"].join("")
or use String.concat
String.concat("a", 2, "c")
or you could write your own concatenate function:
var concat = function(/* args */) {
/*
* Something involving a loop through arguments
*/
}
or use a 3rd-party sprintf function, such as http://www.diveintojavascript.com/projects/javascript-sprintf
You could consider using coffeescript to write the code (which has interpolation like Ruby ie #{foo}).
It 'compiles' down to javascript - so you will end up with javascript like what you've written, but without the need to write/maintain the +++ code you're tired of
I realize that asking you to consider another language is on the edge of being a valid answer or not but considering the way coffeescript works, and that one of your tags is Ruby, I'm hoping it'll pass.
As a Javascript curiosity, you can implement something that basically does Ruby-like interpolation:
sub = function(str) {
return str.replace(/#\{(.*?)\}/g,
function(whole, expr) {
return eval(expr)
})
}
js> y = "world!"
world!
js> sub("Hello #{y}")
Hello world!
js> sub("1 + 1 = #{1 + 1}")
1 + 1 = 2
Using it on anything but string literals is asking for trouble, and it's probably quite slow anyways (although I haven't measured). Just thought I'd let you know.
Direct answer: No javascript doesn't support string interpolation.
The only way is to implement it yourself or use a third party lib who does it for you.
EDIT
As Marcos added in comments theres a proposal for ECMAScript 6 (Harmony), so we can have proper string interpolation:
var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and\nnot ${2 * a + b}.`);
// "Fifteen is 15 and
// not 20."
Please see more information here.
I just wrote this hacky function to do this. Usage is as follows:
interpolate("#{gimme}, #{shelter}", {gimme:'hello', shelter:'world'})
// returns "hello, world"
And the implementation:
interpolate = function(formatString, data) {
var i, len,
formatChar,
prevFormatChar,
prevPrevFormatChar;
var prop, startIndex = -1, endIndex = -1,
finalString = '';
for (i = 0, len = formatString.length; i<len; ++i) {
formatChar = formatString[i];
prevFormatChar = i===0 ? '\0' : formatString[i-1],
prevPrevFormatChar = i<2 ? '\0' : formatString[i-2];
if (formatChar === '{' && prevFormatChar === '#' && prevPrevFormatChar !== '\\' ) {
startIndex = i;
} else if (formatChar === '}' && prevFormatChar !== '\\' && startIndex !== -1) {
endIndex = i;
finalString += data[formatString.substring(startIndex+1, endIndex)];
startIndex = -1;
endIndex = -1;
} else if (startIndex === -1 && startIndex === -1){
if ( (formatChar !== '\\' && formatChar !== '#') || ( (formatChar === '\\' || formatChar === '#') && prevFormatChar === '\\') ) {
finalString += formatChar;
}
}
}
return finalString;
};
I wanted to write a regex to count the number of spaces/tabs/newline in a chunk of text. So I naively wrote the following:-
numSpaces : function(text) {
return text.match(/\s/).length;
}
For some unknown reasons it always returns 1. What is the problem with the above statement? I have since solved the problem with the following:-
numSpaces : function(text) {
return (text.split(/\s/).length -1);
}
tl;dr: Generic Pattern Counter
// THIS IS WHAT YOU NEED
const count = (str) => {
const re = /YOUR_PATTERN_HERE/g
return ((str || '').match(re) || []).length
}
For those that arrived here looking for a generic way to count the number of occurrences of a regex pattern in a string, and don't want it to fail if there are zero occurrences, this code is what you need. Here's a demonstration:
/*
* Example
*/
const count = (str) => {
const re = /[a-z]{3}/g
return ((str || '').match(re) || []).length
}
const str1 = 'abc, def, ghi'
const str2 = 'ABC, DEF, GHI'
console.log(`'${str1}' has ${count(str1)} occurrences of pattern '/[a-z]{3}/g'`)
console.log(`'${str2}' has ${count(str2)} occurrences of pattern '/[a-z]{3}/g'`)
Original Answer
The problem with your initial code is that you are missing the global identifier:
>>> 'hi there how are you'.match(/\s/g).length;
4
Without the g part of the regex it will only match the first occurrence and stop there.
Also note that your regex will count successive spaces twice:
>>> 'hi there'.match(/\s/g).length;
2
If that is not desirable, you could do this:
>>> 'hi there'.match(/\s+/g).length;
1
As mentioned in my earlier answer, you can use RegExp.exec() to iterate over all matches and count each occurrence; the advantage is limited to memory only, because on the whole it's about 20% slower than using String.match().
var re = /\s/g,
count = 0;
while (re.exec(text) !== null) {
++count;
}
return count;
(('a a a').match(/b/g) || []).length; // 0
(('a a a').match(/a/g) || []).length; // 3
Based on https://stackoverflow.com/a/48195124/16777 but fixed to actually work in zero-results case.
Here is a similar solution to #Paolo Bergantino's answer, but with modern operators. I'll explain below.
const matchCount = (str, re) => {
return str?.match(re)?.length ?? 0;
};
// usage
let numSpaces = matchCount(undefined, /\s/g);
console.log(numSpaces); // 0
numSpaces = matchCount("foobarbaz", /\s/g);
console.log(numSpaces); // 0
numSpaces = matchCount("foo bar baz", /\s/g);
console.log(numSpaces); // 2
?. is the optional chaining operator. It allows you to chain calls as deep as you want without having to worry about whether there is an undefined/null along the way. Think of str?.match(re) as
if (str !== undefined && str !== null) {
return str.match(re);
} else {
return undefined;
}
This is slightly different from #Paolo Bergantino's. Theirs is written like this: (str || ''). That means if str is falsy, return ''. 0 is falsy. document.all is falsy. In my opinion, if someone were to pass those into this function as a string, it would probably be because of programmer error. Therefore, I'd rather be informed I'm doing something non-sensible than troubleshoot why I keep on getting a length of 0.
?? is the nullish coalescing operator. Think of it as || but more specific. If the left hand side of || evaluates to falsy, it executes the right-hand side. But ?? only executes if the left-hand side is undefined or null.
Keep in mind, the nullish coalescing operator in ?.length ?? 0 will return the same thing as using ?.length || 0. The difference is, if length returns 0, it won't execute the right-hand side... but the result is going to be 0 whether you use || or ??.
Honestly, in this situation I would probably change it to || because more JavaScript developers are familiar with that operator. Maybe someone could enlighten me on benefits of ?? vs || in this situation, if any exist.
Lastly, I changed the signature so the function can be used for any regex.
Oh, and here is a typescript version:
const matchCount = (str: string, re: RegExp) => {
return str?.match(re)?.length ?? 0;
};
('my string'.match(/\s/g) || []).length;
This is certainly something that has a lot of traps. I was working with Paolo Bergantino's answer, and realising that even that has some limitations. I found working with string representations of dates a good place to quickly find some of the main problems. Start with an input string like this:
'12-2-2019 5:1:48.670'
and set up Paolo's function like this:
function count(re, str) {
if (typeof re !== "string") {
return 0;
}
re = (re === '.') ? ('\\' + re) : re;
var cre = new RegExp(re, 'g');
return ((str || '').match(cre) || []).length;
}
I wanted the regular expression to be passed in, so that the function is more reusable, secondly, I wanted the parameter to be a string, so that the client doesn't have to make the regex, but simply match on the string, like a standard string utility class method.
Now, here you can see that I'm dealing with issues with the input. With the following:
if (typeof re !== "string") {
return 0;
}
I am ensuring that the input isn't anything like the literal 0, false, undefined, or null, none of which are strings. Since these literals are not in the input string, there should be no matches, but it should match '0', which is a string.
With the following:
re = (re === '.') ? ('\\' + re) : re;
I am dealing with the fact that the RegExp constructor will (I think, wrongly) interpret the string '.' as the all character matcher \.\
Finally, because I am using the RegExp constructor, I need to give it the global 'g' flag so that it counts all matches, not just the first one, similar to the suggestions in other posts.
I realise that this is an extremely late answer, but it might be helpful to someone stumbling along here. BTW here's the TypeScript version:
function count(re: string, str: string): number {
if (typeof re !== 'string') {
return 0;
}
re = (re === '.') ? ('\\' + re) : re;
const cre = new RegExp(re, 'g');
return ((str || '').match(cre) || []).length;
}
Using modern syntax avoids the need to create a dummy array to count length 0
const countMatches = (exp, str) => str.match(exp)?.length ?? 0;
Must pass exp as RegExp and str as String.
how about like this
function isint(str){
if(str.match(/\d/g).length==str.length){
return true;
}
else {
return false
}
}
How can I check if a string ends with a particular character in JavaScript?
Example: I have a string
var str = "mystring#";
I want to know if that string is ending with #. How can I check it?
Is there a endsWith() method in JavaScript?
One solution I have is take the length of the string and get the last character and check it.
Is this the best way or there is any other way?
UPDATE (Nov 24th, 2015):
This answer is originally posted in the year 2010 (SIX years back.) so please take note of these insightful comments:
Shauna -
Update for Googlers - Looks like ECMA6 adds this function. The MDN article also shows a polyfill. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
T.J. Crowder -
Creating substrings isn't expensive on modern browsers; it may well have been in 2010 when this answer was posted. These days, the simple this.substr(-suffix.length) === suffix approach is fastest on Chrome, the same on IE11 as indexOf, and only 4% slower (fergetaboutit territory) on Firefox: https://jsben.ch/OJzlM And faster across the board when the result is false: jsperf.com/endswith-stackoverflow-when-false Of course, with ES6 adding endsWith, the point is moot. :-)
ORIGINAL ANSWER:
I know this is a year old question... but I need this too and I need it to work cross-browser so... combining everyone's answer and comments and simplifying it a bit:
String.prototype.endsWith = function(suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
Doesn't create a substring
Uses native indexOf function for fastest results
Skip unnecessary comparisons using the second parameter of indexOf to skip ahead
Works in Internet Explorer
NO Regex complications
Also, if you don't like stuffing things in native data structure's prototypes, here's a standalone version:
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
EDIT: As noted by #hamish in the comments, if you want to err on the safe side and check if an implementation has already been provided, you can just adds a typeof check like so:
if (typeof String.prototype.endsWith !== 'function') {
String.prototype.endsWith = function(suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
}
/#$/.test(str)
will work on all browsers, doesn't require monkey patching String, and doesn't require scanning the entire string as lastIndexOf does when there is no match.
If you want to match a constant string that might contain regular expression special characters, such as '$', then you can use the following:
function makeSuffixRegExp(suffix, caseInsensitive) {
return new RegExp(
String(suffix).replace(/[$%()*+.?\[\\\]{|}]/g, "\\$&") + "$",
caseInsensitive ? "i" : "");
}
and then you can use it like this
makeSuffixRegExp("a[complicated]*suffix*").test(str)
Unfortunately not.
if( "mystring#".substr(-1) === "#" ) {}
Come on, this is the correct endsWith implementation:
String.prototype.endsWith = function (s) {
return this.length >= s.length && this.substr(this.length - s.length) == s;
}
using lastIndexOf just creates unnecessary CPU loops if there is no match.
This version avoids creating a substring, and doesn't use regular expressions (some regex answers here will work; others are broken):
String.prototype.endsWith = function(str)
{
var lastIndex = this.lastIndexOf(str);
return (lastIndex !== -1) && (lastIndex + str.length === this.length);
}
If performance is important to you, it would be worth testing whether lastIndexOf is actually faster than creating a substring or not. (It may well depend on the JS engine you're using...) It may well be faster in the matching case, and when the string is small - but when the string is huge it needs to look back through the whole thing even though we don't really care :(
For checking a single character, finding the length and then using charAt is probably the best way.
Didn't see apporach with slice method. So i'm just leave it here:
function endsWith(str, suffix) {
return str.slice(-suffix.length) === suffix
}
From developer.mozilla.org String.prototype.endsWith()
Summary
The endsWith() method determines whether a string ends with the characters of another string, returning true or false as appropriate.
Syntax
str.endsWith(searchString [, position]);
Parameters
searchString :
The characters to be searched for at the end of this string.
position :
Search within this string as if this string were only this long; defaults to this string's actual length, clamped within the range established by this string's length.
Description
This method lets you determine whether or not a string ends with another string.
Examples
var str = "To be, or not to be, that is the question.";
alert( str.endsWith("question.") ); // true
alert( str.endsWith("to be") ); // false
alert( str.endsWith("to be", 19) ); // true
Specifications
ECMAScript Language Specification 6th Edition (ECMA-262)
Browser compatibility
return this.lastIndexOf(str) + str.length == this.length;
does not work in the case where original string length is one less than search string length and the search string is not found:
lastIndexOf returns -1, then you add search string length and you are left with the original string's length.
A possible fix is
return this.length >= str.length && this.lastIndexOf(str) + str.length == this.length
if( ("mystring#").substr(-1,1) == '#' )
-- Or --
if( ("mystring#").match(/#$/) )
Just another quick alternative that worked like a charm for me, using regex:
// Would be equivalent to:
// "Hello World!".endsWith("World!")
"Hello World!".match("World!$") != null
String.prototype.endsWith = function(str)
{return (this.match(str+"$")==str)}
String.prototype.startsWith = function(str)
{return (this.match("^"+str)==str)}
I hope this helps
var myStr = “ Earth is a beautiful planet ”;
var myStr2 = myStr.trim();
//==“Earth is a beautiful planet”;
if (myStr2.startsWith(“Earth”)) // returns TRUE
if (myStr2.endsWith(“planet”)) // returns TRUE
if (myStr.startsWith(“Earth”))
// returns FALSE due to the leading spaces…
if (myStr.endsWith(“planet”))
// returns FALSE due to trailing spaces…
the traditional way
function strStartsWith(str, prefix) {
return str.indexOf(prefix) === 0;
}
function strEndsWith(str, suffix) {
return str.match(suffix+"$")==suffix;
}
I don't know about you, but:
var s = "mystring#";
s.length >= 1 && s[s.length - 1] == '#'; // will do the thing!
Why regular expressions? Why messing with the prototype? substr? c'mon...
I just learned about this string library:
http://stringjs.com/
Include the js file and then use the S variable like this:
S('hi there').endsWith('hi there')
It can also be used in NodeJS by installing it:
npm install string
Then requiring it as the S variable:
var S = require('string');
The web page also has links to alternate string libraries, if this one doesn't take your fancy.
If you're using lodash:
_.endsWith('abc', 'c'); // true
If not using lodash, you can borrow from its source.
function strEndsWith(str,suffix) {
var reguex= new RegExp(suffix+'$');
if (str.match(reguex)!=null)
return true;
return false;
}
So many things for such a small problem, just use this Regular Expression
var str = "mystring#";
var regex = /^.*#$/
if (regex.test(str)){
//if it has a trailing '#'
}
Its been many years for this question. Let me add an important update for the users who wants to use the most voted chakrit's answer.
'endsWith' functions is already added to JavaScript as part of ECMAScript 6 (experimental technology)
Refer it here: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
Hence it is highly recommended to add check for the existence of native implementation as mentioned in the answer.
function check(str)
{
var lastIndex = str.lastIndexOf('/');
return (lastIndex != -1) && (lastIndex == (str.length - 1));
}
A way to future proof and/or prevent overwriting of existing prototype would be test check to see if it has already been added to the String prototype. Here's my take on the non-regex highly rated version.
if (typeof String.endsWith !== 'function') {
String.prototype.endsWith = function (suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
}
#chakrit's accepted answer is a solid way to do it yourself. If, however, you're looking for a packaged solution, I recommend taking a look at underscore.string, as #mlunoe pointed out. Using underscore.string, the code would be:
function endsWithHash(str) {
return _.str.endsWith(str, '#');
}
After all those long tally of answers, i found this piece of code simple and easy to understand!
function end(str, target) {
return str.substr(-target.length) == target;
}
if you dont want to use lasIndexOf or substr then why not just look at the string in its natural state (ie. an array)
String.prototype.endsWith = function(suffix) {
if (this[this.length - 1] == suffix) return true;
return false;
}
or as a standalone function
function strEndsWith(str,suffix) {
if (str[str.length - 1] == suffix) return true;
return false;
}
String.prototype.endWith = function (a) {
var isExp = a.constructor.name === "RegExp",
val = this;
if (isExp === false) {
a = escape(a);
val = escape(val);
} else
a = a.toString().replace(/(^\/)|(\/$)/g, "");
return eval("/" + a + "$/.test(val)");
}
// example
var str = "Hello";
alert(str.endWith("lo"));
alert(str.endWith(/l(o|a)/));
This builds on #charkit's accepted answer allowing either an Array of strings, or string to passed in as an argument.
if (typeof String.prototype.endsWith === 'undefined') {
String.prototype.endsWith = function(suffix) {
if (typeof suffix === 'String') {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
}else if(suffix instanceof Array){
return _.find(suffix, function(value){
console.log(value, (this.indexOf(value, this.length - value.length) !== -1));
return this.indexOf(value, this.length - value.length) !== -1;
}, this);
}
};
}
This requires underscorejs - but can probably be adjusted to remove the underscore dependency.
if(typeof String.prototype.endsWith !== "function") {
/**
* String.prototype.endsWith
* Check if given string locate at the end of current string
* #param {string} substring substring to locate in the current string.
* #param {number=} position end the endsWith check at that position
* #return {boolean}
*
* #edition ECMA-262 6th Edition, 15.5.4.23
*/
String.prototype.endsWith = function(substring, position) {
substring = String(substring);
var subLen = substring.length | 0;
if( !subLen )return true;//Empty string
var strLen = this.length;
if( position === void 0 )position = strLen;
else position = position | 0;
if( position < 1 )return false;
var fromIndex = (strLen < position ? strLen : position) - subLen;
return (fromIndex >= 0 || subLen === -fromIndex)
&& (
position === 0
// if position not at the and of the string, we can optimise search substring
// by checking first symbol of substring exists in search position in current string
|| this.charCodeAt(fromIndex) === substring.charCodeAt(0)//fast false
)
&& this.indexOf(substring, fromIndex) === fromIndex
;
};
}
Benefits:
This version is not just re-using indexOf.
Greatest performance on long strings. Here is a speed test http://jsperf.com/starts-ends-with/4
Fully compatible with ecmascript specification. It passes the tests
Do not use regular expressions. They are slow even in fast languages. Just write a function that checks the end of a string. This library has nice examples: groundjs/util.js.
Be careful adding a function to String.prototype. This code has nice examples of how to do it: groundjs/prototype.js
In general, this is a nice language-level library: groundjs
You can also take a look at lodash
all of them are very useful examples. Adding String.prototype.endsWith = function(str) will help us to simply call the method to check if our string ends with it or not, well regexp will also do it.
I found a better solution than mine. Thanks every one.
For coffeescript
String::endsWith = (suffix) ->
-1 != #indexOf suffix, #length - suffix.length
This is the implementation of endsWith:
String.prototype.endsWith = function (str) {
return (this.length >= str.length) && (this.substr(this.length - str.length) === str);
}
7 years old post, but I was not able to understand top few posts, because they are complex. So, I wrote my own solution:
function strEndsWith(str, endwith)
{
var lastIndex = url.lastIndexOf(endsWith);
var result = false;
if (lastIndex > 0 && (lastIndex + "registerc".length) == url.length)
{
result = true;
}
return result;
}