브라우저의 이해 #2 히스토리 그리고 history API
자바스크립트 정규 표현식과 test 메소드, 그리고 플래그 g
2018-07-26
Explanation
개발을 하다가 우연히 생각도 못 한 결과 값을 보고 깜짝 놀라, 조금 검색해보고 알게 된 정보를 조금 적어보려 합니다.
(많은 분들은 이미 알고 계시겠지만, 저는 처음에 예상치 못한 결과에 신기했네요.)
1 2 3 4 5 6 7 8 9 10 11 12 |
(function() { const arr = ['abc', 'abc', 'abc', 'abc']; const reg = new RegExp('a', 'g'); const len = arr.length; let result = []; let i; for(i=0; i<len; i++) { result.push(reg.test(arr[i])); } return result; })(); |
위와 같은 코드가 있다고 했을때 리턴값 result는 어떻게 나올까요??
저는 뭔가 너무도 당연하게 [true, true, true, true]를 생각했는데
웬걸… 리턴 값은 [true, false, true, false]가 나온답니다.
여기서 포인트는 저 글로벌 플래그 g에 있는 것 같아요. ‘글로벌’이라는 단어만 들어도 뭔가 전체를 대상으로 하는 의미를 가진거 같아요. 개인적으로 지난 시간을 떠올렸을 때 정규 표현식을 많이 사용한 건 대충 문자열에서 특정 부분의 값을 바꿀 때 많이 사용 했던 거 같아요. 예를 들면
1 2 3 4 |
let text = '안녕하세요. 나쁜 아침이에요, 오늘 하루가 나쁜 하루가 될거 같아요.'; text = text.replace(/나쁜/g, '좋은'); console.log(text); // 안녕하세요. 좋은 아침이에요, 오늘 하루가 좋은 하루가 될거 같아요. |
뭐 이런식이겠죠?
그래서 저에게 g 플래그는 저렇게 ‘대상 문자열의 전체에서 찾는 것이구나’ 정도로 생각하고 말았던 거 같아요. 그런데 생각해보면 test() 메서드에서는 위 replace() 메서드에서 사용된 g 플래그는 아무런 의미가 없죠. 해당하는 문자 패턴이 1개 이거나 100개 이거나 결과 값은 동일한 true 일 테니까요.
정규 표현식에 사용되는 g 플래그는 사용되는 매서드에 따라서 조금씩 그 의미?? 역할?? 이 다르답니다.
처음 이야기로 돌아가면 test() 메서드에서 g는 검색을 실행한 문자열의 lastIndex를 기억할지의 여부로 사용된답니다. 아까의 예제로 돌아가면 ‘a’라는 패턴을 가지고 배열 첫 번째인 ‘abc’ 문자열과 비교해서 첫 번째에서 패턴을 발견하고, g 플래그를 사용했다면 true를 리턴하며 lastIndex로 일치한 부분의 바로 다음 위치을 기억한답니다.
그러면 lastIndex 값은 1이 되겠지요? 그리고 두 번째 배열의 값인 ‘abc’와 비교할 때는 lastIndex 값이 1이기 때문에 ‘bc’를 비교하게 되고 매칭되는 문자열 없기 때문에 false를 리턴하게 된답니다. 그리고 패턴이 일치하지 않았기 때문에 lastIndex 값은 다시 초깃값 -1를 가지게 되고 나머지 배열에서 다시 반복하여 true, 그리고 false를 리턴하게 됩것입니다.