基于正则表达式过滤数组:结果疑问的技术咨询
Let's break down exactly what's happening here—this boils down to a super common gotcha with JavaScript regexes that have the global (g) flag enabled.
The Root Cause: lastIndex Behavior with Global Regexes
When you create a regex with the g flag, the RegExp object keeps track of a lastIndex property that marks where the next match should start. Every time you call test() or exec() on that regex, it updates lastIndex to the position right after the end of the last match.
The problem? This lastIndex state sticks around across calls—even when you're testing completely different strings in your filter loop. That means your regex isn't starting from the beginning of each new string; it's picking up where it left off with the previous one.
Let's walk through your specific example step by step:
- First array element:
'S2A_MSIL1C_20180213T041901_N0206_R090_T46QCH_20180213T075744.SAFE'- No
T46QCJpresent, and allScharacters are uppercase (your regex looks for lowercases).test()returnsfalse, andlastIndexresets to0.
- No
- Second array element:
'S2B_MSIL1C_20180208T041929_N0206_R090_T46QCJ_20180208T075342.SAFE'- Contains
T46QCJ, sotest()finds a match, returnstrue, and setslastIndexto the position right after the matched substring.
- Contains
- Third array element:
'S2A_MSIL1C_20180213T041901_N0206_R090_T46QCJ_20180213T075744.SAFE'- Now
test()starts at thelastIndexset by the previous match, which is past the position ofT46QCJin this string. It doesn't find a match, returnsfalse, andlastIndexresets to0.
- Now
- Fourth array element:
'S2B_MSIL1C_20180310T041559_N0206_R090_T46QDK_20180310T075716.SAFE'- No
T46QCJor lowercases, sotest()returnsfalse.
- No
That's why only the second element ends up in your filtered array.
Fixes to Resolve the Issue
You've got a few straightforward options here:
1. Remove the Global (g) Flag
Since you're only checking if a string contains your pattern (not finding all occurrences), you don't need the global flag. This disables lastIndex tracking entirely:
const regex = new RegExp('(T46QCJ|s)'); // No 'g' flag const filtered = array.filter(e => regex.test(e));
2. Reset lastIndex Manually Before Each Test
If you need to keep the global flag for some reason, explicitly reset lastIndex to 0 before testing each string:
const regex = new RegExp('(T46QCJ|s)', 'g'); const filtered = array.filter(e => { regex.lastIndex = 0; // Start matching from the beginning of the string return regex.test(e); });
3. Use String Methods Instead (Simpler Option)
For basic substring checks, you can skip regex entirely and use includes() (with a case adjustment for the lowercase s):
const filtered = array.filter(e => e.includes('T46QCJ') || e.toLowerCase().includes('s'));
内容的提问来源于stack exchange,提问作者dwalin93

