Javascript е добре известен със своите странности, но все още се използва широко в програмистката общност. Аз самият използвам Javascript всеки ден, изгарям от него, но продължавам да го използвам.
Наскоро се занимавах с регулярни изрази в Javascript и открих това мистериозно поведение при използване на глобален флаг g
.
Нека първо започнем с пример.
const MUSTACHE_REGEX = /{{/g function hasMustache (template) { return MUSTACHE_REGEX.test(template) }
Функцията hasMustache
връща булево значение, независимо дали низът съдържа две последователни фигурни скоби {{
или не.
Сега, ако използвате горната функция два пъти на един и същ низ, тя ще върне true
за първи път и след това false
.
console.log(hasMustache('Hello {{ username }}')) // true console.log(hasMustache('Hello {{ username }}')) // false
„Вижте примера на живо“
Защо това се случва?
Javascript съхранява последния съответстващ индекс, когато използва функции test
или exec
с флаг g
.
Което означава, че всеки нов низ, предаден на функцията test
, ще започне да съвпада от стария индекс.
console.log(hasMustache('Hello {{ username }}')) console.log(MUSTACHE_REGEX.lastIndex) // 8
Сега, когато извикаме hasMustache
отново, търсенето започна от индекс 8 и следователно нямаше съвпадение.
Да кажем, че променим низа Hello {{ username }}
с по-дълъг низ, в който {{
се появява след 8-ия индекс.
console.log(hasMustache('Hello {{ username }}')) console.log(hasMustache('A bit longer string {{ username }}'))
БУМ! Това е true
и за двата низа.
Как да поправя?
Използваме флаг g
, когато искаме всички срещания на съвпадение и в нашия случай глобалният флаг беше излишен, защото всичко, от което се нуждаехме, беше boolean
.
С две думи
- Не използвайте
g
, когато използвате метод regextest
. - Когато използвате
exec
, поставете го в цикъл while, за да получите всички съвпадащи събития.