Така че основно аз написах тази функция, за да мога да преброя броя на срещанията на подниз в низ:
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) {
// needle.global = true;
return this.match(needle).length;
} return 0;
};
Самият метод се представя доста добре и както RegExp, така и базираните на низове търсения са доста сравними по отношение на времето за изпълнение (и двете ~2ms за целия огромен "451 Fahrenheit" на Рей Бредбъри, търсейки всички "the"s).
Това, което ме притеснява обаче, е невъзможността за промяна на флага на предоставения екземпляр на RegExp. Няма смисъл да се извиква String.prototype.match в тази функция без глобалният флаг на предоставения регулярен израз да е зададен на true, тъй като тогава ще се отбележи само първото появяване. Със сигурност бихте могли да зададете флага ръчно на всеки RegExp, подаден на функцията, но бих предпочел да мога да клонирам и след това да манипулирам флаговете на предоставения регулярен израз.
Колкото и да е удивително, не ми е разрешено да го правя, тъй като флагът RegExp.prototype.global (по-точно всички флагове) изглежда само за четене. Оттук и коментираният ред 8.
Въпросът ми е: Има ли хубав начин за промяна на флаговете на RegExp обект?
Наистина не искам да правя неща като това:
if(!expression.global)
expression = eval(expression.toString() + "g");
Някои реализации може да не поддържат RegExp.prototype.toString и просто да го наследят от Object.prototype, или може да е изцяло различно форматиране. И като начало изглежда като лоша практика за кодиране.