С учетом этого кода:
var reg = /a/g;
console.log(reg.test("a"));
console.log(reg.test("a"));
Получаю этот результат:
true
false
Я понятия не имею, как это может произойти. Я тестировал как в Node.js(v8), так и в браузере Firefox.
С учетом этого кода:
var reg = /a/g;
console.log(reg.test("a"));
console.log(reg.test("a"));
Получаю этот результат:
true
false
Я понятия не имею, как это может произойти. Я тестировал как в Node.js(v8), так и в браузере Firefox.
Чтобы решить проблему, вы можете удалить флаг g
или reset lastIndex
, как в
var reg = /a/g;
console.log(reg.test("a"));
reg.lastIndex = 0;
console.log(reg.test("a"));
Проблема возникает из-за того, что test
основывается на exec
, который ищет больше совпадений после первого, если передается одна и та же строка, и присутствует флаг g
.
15.10.6.3
RegExp.prototype.test(string)
# Ⓣ ⓇВыполняются следующие шаги:
- Пусть совпадение будет результатом оценки алгоритма
RegExp.prototype.exec
(15.10.6.2) на этом объектеRegExp
с использованием строки в качестве аргумента.- Если совпадение не
null
, вернитеtrue
; else returnfalse
.
Ключевой частью exec
является шаг 6 15.10.6.2:
6. Пусть global будет результатом вызова внутреннего метода [[Get]] R с аргументом "global".
7. Если глобальное значение false, то пусть я = 0.
Если i
не reset равно 0, то exec
(и поэтому test
) не начинает смотреть начало строки.
Это полезно для exec
, потому что вы можете циклически обрабатывать каждое соответствие:
var myRegex = /o/g;
var myString = "fooo";
for (var match; match = myRegex.exec(myString);) {
alert(match + " at " + myRegex.lastIndex);
}
но, очевидно, это не так полезно для test
.
Обычно выбирается тест, чтобы проверить, совпадает ли какой-либо шаблон, но глобальный флаг позволяет вам перебирать строку для подсчета совпадений или, подобно exec, делать что-то с каждым lastIndex. Другое использование - установить lastIndex из rx непосредственно перед тем, как тест будет сформирован, чтобы игнорировать совпадения перед некоторым символьным индексом.
var count=0, rx=/\s+/g, rx.lastIndex=100;
while(rx.test(string))count++;