So basically I wrote myself this function so as to be able to count the number of occurances of a Substring in a String:
String.prototype.numberOf = function
First, your current code does not work correctly when needle
is a regex which does not match. i.e. The following line:
return this.match(needle).length;
The match
method returns null
when there is no match. A JavaScript error is then generated when the length
property of null
is (unsuccessfully) accessed. This is easily fixed like so:
var m = this.match(needle);
return m ? m.length : 0;
Now to the problem at hand. You are correct when you say that global
, ignoreCase
and multiline
are read only properties. The only option is to create a new RegExp. This is easily done since the regex source string is stored in the re.source
property. Here is a tested modified version of your function which corrects the problem above and creates a new RegExp object when needle
does not already have its global
flag set:
String.prototype.numberOf = function(needle) {
var num = 0,
lastIndex = 0;
if (typeof needle === "string" || needle instanceof String) {
while((lastIndex = this.indexOf(needle, lastIndex) + 1) > 0)
{num++;} return num;
} else if(needle instanceof RegExp) {
if (!needle.global) {
// If global flag not set, create new one.
var flags = "g";
if (needle.ignoreCase) flags += "i";
if (needle.multiline) flags += "m";
needle = RegExp(needle.source, flags);
}
var m = this.match(needle);
return m ? m.length : 0;
}
return 0;
};
There isn't much you can do but I highly recommend you avoid using eval
. You can extend the RegExp prototype to help you out.
RegExp.prototype.flags = function () {
return (this.ignoreCase ? "i" : "")
+ (this.multiline ? "m" : "")
+ (this.global ? "g" : "");
};
var reg1 = /AAA/i;
var reg2 = new RegExp(reg1.source, reg1.flags() + 'g');
var globalRegex = new RegExp(needle.source, "g");
Live Demo EDIT: The m was only for the sake of demonstrating that you can set multiple modifiers
var regex = /find/;
var other = new RegExp(regex.source, "gm");
alert(other.global);
alert(other.multiline);
r = new Regexp(r.source, r.flags + (r.global ? "" : "g"));