Запуск exec() внутри цикла в Javascript

Я не уверен, в чем проблема, но запуск exec() внутри цикла for в Javascript (Nodejs, консоль Chrome, консоль Firefox) дает неправильные результаты. Насколько мне известно, exec() — это синхронный метод, вызываемый внутри синхронного цикла, который должен давать ожидаемый результат.

const FILTER_REGEX = /(\w+)\s+(below|under|lesser than|lower than|above|over|more than|higher than|greater than|equals|equal to|same as|>|<|=)\s+(\d+)/gi;
const searchQuery = "Package Quantity > 50000 Date yearly ListPrice above 100";
const filterMatches = searchQuery.match(FILTER_REGEX) || [];
for(const filterMatch of filterMatches) {
    const filterMatchGroups = FILTER_REGEX.exec(filterMatch);
    console.info(`filterMatch: ${filterMatch}, filterMatchGroups: ${filterMatchGroups}`);
}

В настоящее время я получаю следующее в качестве вывода: иногда filterMatchGroups для первой строки становится нулевым и дает filterMatchGroups для второй.

filterMatch: Quantity > 50000, filterMatchGroups: Quantity > 50000,Quantity,>,50000
filterMatch: ListPrice above 100, filterMatchGroups: null

@CertainPerfomance Как это дубликат этого вопроса?

PrivateOmega 04.03.2019 05:49

Почти так и есть, но этот вопрос пока открыт. Проблема в том, что ваш FILTER_REGEX является глобальным и имеет состояние (свойство lastIndex). Если вы каждый раз запускаете новое регулярное выражение, результат будет таким, как ожидалось. jsfiddle.net/fy0p9jbk

CertainPerformance 04.03.2019 05:51
stackoverflow.com/questions/1520800/…
Andreas 04.03.2019 05:52

@CertainPerformance Разве глобальный идентификатор не означает, что он находит все совпадения, а не останавливается на первом, верно? Поправьте меня, если я ошибаюсь.

PrivateOmega 04.03.2019 05:52

Не тогда, когда вы используете .exec, который вернет совпадение следующий (пока оно не дойдет до конца и не сможет найти больше совпадений, а затем начнется сначала)

CertainPerformance 04.03.2019 05:53

@Andreas Спасибо, я не знал, что он также использует последний индекс для следующей проверки, поэтому я надеюсь, что сброс lastIndex регулярного выражения должен сделать все хорошо. Это похоже на действительно хорошую ловушку, которую я бы никогда не понял, если бы не спросил.

PrivateOmega 04.03.2019 05:56

Я вообще не заморачиваюсь с exec; это может немного снизить производительность, но я обычно использую replace для поиска всех результатов вместо exec (даже если я не заинтересован в замене чего-либо). Нет надоедливого состояния с replace.

Amadan 04.03.2019 06:22

@Amadan Но как получить группы из replace ()?

PrivateOmega 04.03.2019 06:50

Вы можете использовать RegExp.lastMatch (MDN говорит, что у него плохая кросс-браузерная совместимость, но я еще не видел, чтобы он терпел неудачу); но стандартным способом будет через параметры обратного вызова.

Amadan 04.03.2019 07:06
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
9
370
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это должно сделать это.

const FILTER_REGEX = /(\w+)\s+(below|under|lesser than|lower than|above|over|more than|higher than|greater than|equals|equal to|same as|>|<|=)\s+(\d+)/gi;
const searchQuery = "Package Quantity > 50000 Date yearly ListPrice above 100";
const filterMatches = searchQuery.match(FILTER_REGEX) || [];
for(const filterMatch of filterMatches) {
    FILTER_REGEX.lastIndex = 0;
    const filterMatchGroups = FILTER_REGEX.exec(filterMatch);
    console.info(`filterMatch: ${filterMatch}, filterMatchGroups: ${filterMatchGroups}`);
}

Единственным видимым отличием является FILTER_REGEX.lastIndex = 0, мы должны сбросить свойство lastIndex регулярного выражения, если нам нужно использовать его снова, иначе оно запустит проверку регулярного выражения из ранее сохраненного lastIndex. Спасибо @CertainPerfomance @Andreas за ссылки и объяснение.

Ссылка: Детальное объяснение

Другие вопросы по теме