Skip to main content
Added the startIndex value
Source Link
Prestaul
  • 85.4k
  • 10
  • 89
  • 85
function reIndexOf(reIn, str, startIndex) { var re = new RegExp(reIn.source, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : '')); re.lastIndex = startIndex || 0; var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; function reLastIndexOf(reIn, str, startIndex) { var src = /\$$/.test(reIn.source) && !/\\\$$/.test(reIn.source) ? reIn.source : reIn.source + '(?![\\S\\s]*' + reIn.source + ')'; var re = new RegExp(src, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : '')); re.lastIndex = startIndex || 0; var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; reIndexOf(/[abc]/, "tommy can eat"); // Returns 6 reIndexOf(/[abc]/, "tommy can eat", 8); // Returns 11 reLastIndexOf(/[abc]/, "tommy can eat"); // Returns 11 
RegExp.prototype.indexOf = function(str, startIndex) { var re = new RegExp(this.source, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : '')); re.lastIndex = startIndex || 0; var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; RegExp.prototype.lastIndexOf = function(str, startIndex) { var src = /\$$/.test(this.source) && !/\\\$$/.test(this.source) ? this.source : this.source + '(?![\\S\\s]*' + this.source + ')'; var re = new RegExp(src, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : ''));   re.lastIndex = startIndex || 0; var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; /[abc]/.indexOf("tommy can eat"); // Returns 6 /[abc]/.indexOf("tommy can eat", 8); // Returns 11 /[abc]/.lastIndexOf("tommy can eat"); // Returns 11 
function reIndexOf(reIn, str) { var re = new RegExp(reIn.source, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : '')); var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; function reLastIndexOf(reIn, str) { var src = /\$$/.test(reIn.source) && !/\\\$$/.test(reIn.source) ? reIn.source : reIn.source + '(?![\\S\\s]*' + reIn.source + ')'; var re = new RegExp(src, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : '')); var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; reIndexOf(/[abc]/, "tommy can eat"); // Returns 6 reLastIndexOf(/[abc]/, "tommy can eat"); // Returns 11 
RegExp.prototype.indexOf = function(str) { var re = new RegExp(this.source, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : '')); var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; RegExp.prototype.lastIndexOf = function(str) { var src = /\$$/.test(this.source) && !/\\\$$/.test(this.source) ? this.source : this.source + '(?![\\S\\s]*' + this.source + ')'; var re = new RegExp(src, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : '')); var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; /[abc]/.indexOf("tommy can eat"); // Returns 6 /[abc]/.lastIndexOf("tommy can eat"); // Returns 11 
function reIndexOf(reIn, str, startIndex) { var re = new RegExp(reIn.source, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : '')); re.lastIndex = startIndex || 0; var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; function reLastIndexOf(reIn, str, startIndex) { var src = /\$$/.test(reIn.source) && !/\\\$$/.test(reIn.source) ? reIn.source : reIn.source + '(?![\\S\\s]*' + reIn.source + ')'; var re = new RegExp(src, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : '')); re.lastIndex = startIndex || 0; var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; reIndexOf(/[abc]/, "tommy can eat"); // Returns 6 reIndexOf(/[abc]/, "tommy can eat", 8); // Returns 11 reLastIndexOf(/[abc]/, "tommy can eat"); // Returns 11 
RegExp.prototype.indexOf = function(str, startIndex) { var re = new RegExp(this.source, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : '')); re.lastIndex = startIndex || 0; var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; RegExp.prototype.lastIndexOf = function(str, startIndex) { var src = /\$$/.test(this.source) && !/\\\$$/.test(this.source) ? this.source : this.source + '(?![\\S\\s]*' + this.source + ')'; var re = new RegExp(src, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : ''));   re.lastIndex = startIndex || 0; var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; /[abc]/.indexOf("tommy can eat"); // Returns 6 /[abc]/.indexOf("tommy can eat", 8); // Returns 11 /[abc]/.lastIndexOf("tommy can eat"); // Returns 11 
Source Link
Prestaul
  • 85.4k
  • 10
  • 89
  • 85

RexExp instances have a lastIndex property already (if they are global) and so what I'm doing is copying the regular expression, modifying it slightly to suit our purposes, exec-ing it on the string and looking at the lastIndex. This will inevitably be faster than looping on the string. (You have enough examples of how to put this onto the string prototype, right?)

function reIndexOf(reIn, str) { var re = new RegExp(reIn.source, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : '')); var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; function reLastIndexOf(reIn, str) { var src = /\$$/.test(reIn.source) && !/\\\$$/.test(reIn.source) ? reIn.source : reIn.source + '(?![\\S\\s]*' + reIn.source + ')'; var re = new RegExp(src, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : '')); var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; reIndexOf(/[abc]/, "tommy can eat"); // Returns 6 reLastIndexOf(/[abc]/, "tommy can eat"); // Returns 11 

You could also prototype the functions onto the RegExp object:

RegExp.prototype.indexOf = function(str) { var re = new RegExp(this.source, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : '')); var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; RegExp.prototype.lastIndexOf = function(str) { var src = /\$$/.test(this.source) && !/\\\$$/.test(this.source) ? this.source : this.source + '(?![\\S\\s]*' + this.source + ')'; var re = new RegExp(src, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : '')); var res = re.exec(str); if(!res) return -1; return re.lastIndex - res[0].length; }; /[abc]/.indexOf("tommy can eat"); // Returns 6 /[abc]/.lastIndexOf("tommy can eat"); // Returns 11 

A quick explanation of how I am modifying the RegExp: For indexOf I just have to ensure that the global flag is set. For lastIndexOf of I am using a negative look-ahead to find the last occurrence unless the RegExp was already matching at the end of the string.