High Performance JavaScript - Chapter 5. Strings and Regular Expressions
Upcoming SlideShare
Loading in...5
×
 

High Performance JavaScript - Chapter 5. Strings and Regular Expressions

on

  • 750 views

High Performance JavaScript - Chapter 5. Strings and Regular Expressions ...

High Performance JavaScript - Chapter 5. Strings and Regular Expressions
하이 퍼포먼스 자바스크립트 - 5장 문자열과 정규 표현식
분량의 한국어 정리 자료 입니다.

Statistics

Views

Total Views
750
Views on SlideShare
728
Embed Views
22

Actions

Likes
1
Downloads
13
Comments
0

2 Embeds 22

http://play.daumcorp.com 17
https://twitter.com 5

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

High Performance JavaScript - Chapter 5. Strings and Regular Expressions High Performance JavaScript - Chapter 5. Strings and Regular Expressions Presentation Transcript

  • 5문자열과 정규 표현식High Performance JavaScript
  • 시작하면서..• 모든 브라우저에서 동작하면서 빠르게 문자열을 조작• 역추적을 줄여 정규 표현식 성능을 올리는 방법• 기타 문자열과 정규 표현식을 효율적으로 쓰는 방법• Steven Levithan : http://blog.stevenlevithan.com/
  • 1 문자열 병합• 매우 성능에 민감할 수 있다.• 루프 + 문자열 병합
  • 문자열 병합 방법방법 예제+ 연산자 str = “a” + “b” + “c”; str = “a”;+= 연산자 str += “b”;array.join() str = [“a”, “b”, “c”].join(“”); str = “a”;string.concat() str = str.concat(“b”, “c”);
  • + 연산자 & += 연산자• 가장 간편한 방법• 모던 브라우저는 충분히 최적화 (IE > 7)
  • + 연산자 & += 연산자 str += “one” + “two”;1. 메모리에 임시 문자열이 만들어집니다.2. 병합된 문자열 “onetwo"를 임시 문자열에 할당합니다.3. 임시 문자열과 str 변수의 현재 값을 합칩니다.4. 결과를 str에 저장합니다.
  • + 연산자 & += 연산자 str += “one”; str += “two”;• 임시 문자열 부분을 제거• 대부분 브라우저에서 10~40% 향상
  • + 연산자 & += 연산자str = str + “one” + “two”;// str = ((str + “one”) + “two”)와 같습니다.
  • + 연산자 & += 연산자
  • + 연산자 & += 연산자• 앞의 테크닉은 IE에서 적용되지 않음• IE8 경우 • 병합할 때 각 부분 문자열의 참조만 저장 • 합쳐진 문자열이 실제로 쓰일때 “진짜” 문자 열에 복사되어 사용 • toString(), length, DOM 추가
  • + 연산자 & += 연산자• IE7 이하 • 매번 문자열을 메모리 새 위치에 복사 largeStr = largeStr + s1 + s2; largeStr += s1 + s2; // 빠름
  • 파이어폭스와 컴파일 타임 폴딩function foldingDemo() { var str = "compile" + "-time" + " folding"; str += "this" + " works" + " too"; str = str + "but" + "not" + "this";}alert(foldingDemo.toString());/* 파이어폭스에서는 이렇게 동작합니다.function foldingDemo() { var str = "compile-time folding"; str += "this works too"; str = str + "but" + "not" + "this";} */
  • 배열 병합• Array.prototype.join• IE7 이하에서만 효과적
  • 배열 병합var str = "Im a thirty-five character string.", newStr = "", appends = 5000;while(appends--) { newStr += str;}
  • 배열 병합var str = "Im a thirty-five character string.", strs = [], newStr, appends = 5000;while(appends--) { strs[strs.length] = str;}newStr = strs.join("");
  • String.prototype.concat// 문자열 하나를 연결합니다.str = str.concat(s1);// 문자열 세 개를 연결합니다.str = str.concat(s1, s2, s3);// 매개변수 목록으로 배열을 넘기먼 배열에 포함된 문자열 전체를 연결합니다.str = String.prototype.concat.apply(str, array);
  • String.prototype.concat• 대부분 브라우저에서 느린편• 배열 매개변수 사용 ≠ 배열 병합• IE7 이하 엄청난 성능 저하
  • 2 정규 표현식 최적화• 역추적 폭주• 어떤 텍스트에 정규 표현식을 적용하는냐에 따라 효율성에 큰 차이
  • 2 정규 표현식 최적화• 역추적 폭주• 어떤 텍스트에 정규 표현식을 적용하는냐에 따라 효율성에 큰 차이
  • • regular expression은 불편하므로 보통은 regex라고 줄여 쓰고 regexes라고 발음 http://ko.forvo.com/
  • • regular expression은 불편하므로 보통은 regex라고 줄여 쓰고 regexes라고 발음 http://ko.forvo.com/
  • 정규식이 동작하는 방법• 1단계 : 컴파일• 2단계 : 시작 위치 결정• 3단계 : 각각의 정규 표현식 토큰을 대조• 4단계 : 성공 또는 실패
  • 1단계 : 컴파일• 정규식 객체를 만들면 브라우저에서 패턴에 에러가 없는지 검사• 실제로 매칭을 수행할 내장 코드 루틴으로 변 경• 변수에 할당하면 패턴을 한 번만 컴파일
  • 2단계 : 시작 위치 결정• 먼저 대상 문자열의 어디부터 검색 시작할지 결정• lastIndex 속성에서 시작 (“g” flag + test, exec)• 4단계에서 일치 패턴을 찾지 못해서 돌아왔을 때는 마지막 시도 다음 문자
  • 3단계 : 각각의 정규식 토큰을 대조• 텍스트와 정규식 패턴을 대조• 토큰 중 일치하지 않는 것이 있으면 앞 지점으 로 역추적 시도
  • 4단계 : 성공 또는 실패• 완전히 일치하는 패턴을 찾으면 성공• 아니라면 2단계로 돌아가서 그 다음 문자부터 다시 시작• 문자열의 마지막까지 일치하는 패턴을 못찾을 때만 실패 선언
  • 역추적 이해하기• 계산을 많이 해야 하고, 쉽게 통제를 벗어나기도• 수량자나 or 연산자를 만날 때 어떻게 진행할지 결 정이 필요 (여러 옵션이 존재하게 됨)• 이후 패턴에서 실패하면 시도해보지 않은 옵션이 있는 마지막 지점까지 역추적!
  • or 연산자와 역추적/h(ello|appy) hippo/.test("hello there, happy hippo");
  • /h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"...
  • /h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo"/h(ello|appy) hippo/ "hello there, happy hippo".../h(ello|appy) hippo/ "hello there, happy hippo"
  • 반복과 역추적var str = "<p>Para 1.</p>" + "<img src = smileY.jpg>" + "<p>Para 2.</p>" + "<div>Div.</div>";/<p>.*</p>/i.test(str);
  • /<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • /<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”/<p>.*</p>/ “<p>Para 1.</p>”
  • 역추적 폭주/<html>[sS]*?<head>[sS]*?<title>[sS]*?</title>[sS]*?</head>[sS]*?<body> • 올바른 HTML 문자열에서 문제가 없지만 •[sS]*?</body>[sS]*?</html> 필수 태그를 생략했을 경우 매우 심각한 문제/
  • 역추적 폭주/ <html><html> <head>[sS]*?<head> <meta charset=”utf-8” />[sS]*?<title> <title>JS Bin</title>[sS]*?</title> </head>[sS]*?</head> <body>[sS]*?<body> <div>Lorem ipsum dolor sit</div>[sS]*?</body> </body>[sS]*?</html> </html>/
  • 역추적 폭주/<html> <html>[sS]*?<head> <head>[sS]*?<title> <meta charset=”utf-8” />[sS]*?</title> <title>JS Bin</title>[sS]*?</head> </head>[sS]*?<body> <body>[sS]*?</body> <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/
  • 역추적 폭주/<html> <html>[sS]*?<head> <head>[sS]*?<title> <meta charset=”utf-8” />[sS]*?</title> <title>JS Bin</title>[sS]*?</head> </head>[sS]*?<body> <body>[sS]*?</body> <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/
  • 역추적 폭주/<html> <html>[sS]*?<head> <head>[sS]*?<title> <meta charset=”utf-8” />[sS]*?</title> <title>JS Bin</title>[sS]*?</head> </head>[sS]*?<body> <body>[sS]*?</body> <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/ 역추적!!! 비교 위치
  • 역추적 폭주/<html> <html>[sS]*?<head> <head>[sS]*?<title> <meta charset=”utf-8” />[sS]*?</title> <title>JS Bin</title>[sS]*?</head> </head>[sS]*?<body> <body>[sS]*?</body> <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/
  • 역추적 폭주/<html> <html>[sS]*?<head> <head>[sS]*?<title> <meta charset=”utf-8” />[sS]*?</title> <title>JS Bin</title>[sS]*?</head> </head>[sS]*?<body> <body>[sS]*?</body> <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/
  • 역추적 폭주/<html> <html>[sS]*?<head> <head>[sS]*?<title> <meta charset=”utf-8” />[sS]*?</title> <title>JS Bin</title>[sS]*?</head> </head>[sS]*?<body> <body>[sS]*?</body> <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/
  • 역추적 폭주/<html> <html>[sS]*?<head> <head>[sS]*?<title> <meta charset=”utf-8” />[sS]*?</title> <title>JS Bin</title>[sS]*?</head> </head>[sS]*?<body> <body>[sS]*?</body> <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/
  • 역추적 폭주• 정규 표현식이 느려지는 이유는• “일치하는 것을 찾는” 데 시간이 걸려서가 아닌• “일치하지 않는다고 판단”하는데 시간이 걸리기 때문
  • 해결책• 필수적인 구분 기호 사이에 들어가는, 정규 표 현식과 일치시킬 문자를 가능한 한 명확하게 써야 /“.*?”/ ⇒ /“[^”rn]*”/
  • 해결책/<html>(?:(?!<head>)[sS])*<head>(?:(?!<title>)[sS])*<title>(?:(?!</title>)[sS])*</title>(?:(?!</head>)[sS])*</head>(?:(?!<body>)[sS])*<body>(?:(?!</body>)[sS])*</body>(?:(?!</html>)[sS])*</html>/ • 하지만, 부정형 룩어헤드 때문에 비효율적
  • 룩어헤드와 역참조를 써서 최소 그룹 흉내내기• (?>...) 최소 그룹 패턴 • 역추적하지 않는 부분식(적극적 부분식) • 부분식이 완전히 일치하면 역추적에 참여하 지 않음
  • 룩어헤드와 역참조를 써서 최소 그룹 흉내내기• (?>...) 최소 그룹 패턴 • 역추적하지 않는 부분식(적극적 부분식) • 부분식이 완전히 일치하면 역추적에 참여하 지 않음• JavaScript는 지원하지 않는다!
  • 룩어헤드와 역참조를 써서 최소 그룹 흉내내기 (?=(최소 그룹으로 만들 패턴))1var str = "<p>Para 1.</p>", reg1 = /<p>([sS]*?</p>)/, // 캡처함. 룩어헤드 없음 reg2 = /<p>(?=([sS]*?</p>))/, // 캡처 + 룩어헤드. 역참조 없음 reg3 = /<p>(?=([sS]*?</p>))1/; // 캡처 + 룩어헤드 + 역잠조alert(reg1.exec(str)); // ["<p>Para 1.</p>", "Para 1.</p>"]alert(reg2.exec(str)); // ["<p>", "Para 1.</p>"]alert(reg3.exec(str)); // ["<p>Para 1.</p>", "Para 1.</p>"]
  • 다시 보는 역추적 폭주/<html> <html>[sS]*?<head> <head>[sS]*?<title> <meta charset=”utf-8” />[sS]*?</title> <title>JS Bin</title>[sS]*?</head> </head>[sS]*?<body> <body>[sS]*?</body> <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/ 역추적!!! 비교 위치
  • 룩어헤드와 역참조를 써서 최소 그룹 흉내내기/<html> <html>(?=([sS]*?<head>))1 <head>(?=([sS]*?<title>))2 <meta charset=”utf-8” />(?=([sS]*?</title>))3 <title>JS Bin</title>(?=([sS]*?</head>))4 </head>(?=([sS]*?<body>))5 <body>(?=([sS]*?</body>))6 <div>Lorem ipsum dolor sit</div>[sS]*?</html> </body>/
  • 중첩된 수량자와 역추적 폭주 /<(?:[^>"]|"[^"]*"|[^]*)*>/• 수량자를 중첩시킬 경우 역추적이 폭주할 가 능성이 크므로 항상 조심 (x+)*• < 다음에 있는 문자를 일치시킬 경우의 수가 매우 많아져서 역추적 폭주 가능성
  • 중첩된 수량자와 역추적 폭주 /(A+A+)+B/.test("AAAAAAAAAA")
  • 중첩된 수량자와 역추적 폭주 /(A+A+)+B/.test("AAAAAAAAAA")첫 번째 A+가 8개 의 문자와 일치하고 두 번째 A十가 2개의 문자와 일치한다변 어떨까요?아니면 첫 번째 A+가 3 개의 문자와 일치하고 두 번째 A+가 2개의 문자와 일치하면서 이 그룹이 두 번반복한 것이라면?그룹을 처음 처리할 때는 첫 번째 A+가 2개의 문자와 일치하고 두 번째 A+가 3개의 문자와 일치 한 다음, 두 번째 처리할 때는 첫 번째 A+가 1개의 문자와 일치하고 두 번째 A+가 4개의 문자와 일치한 것이라면?
  • 중첩된 수량자와 역추적 폭주 /(A+A+)+B/.test("AAAAAAAAAA") 첫 번째 A+가 8개 의 문자와 일치하고 두 번째 A十가 2개의 문자와 일치한다변 어떨까요? 아니면 첫 번째 A+가 3 개의 문자와 일치하고 두 번째 A+가 2개의 문자와 일치하면서 이 그룹이 두 번 반복한 것이라면? 그룹을 처음 처리할 때는 첫 번째 A+가 2개의 문자와 일치하고 두 번째 A+가 3개의 문자와 일치 한 다 음, 두 번째 처리할 때는 첫 번째 A+가 1개의 문자와 일치하고 두 번째 A+가 4개의 문자와 일치한 것이라 면? n = 문자열 길이 2^n 계산“AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA” = 34,359,738,368번
  • 벤치마크 시 참고할 것
  • 벤치마크 시 참고할 것• 정규 표현식 성능은 어떤 문자열에 적용하느 냐에 따라 천차만별
  • 벤치마크 시 참고할 것• 정규 표현식 성능은 어떤 문자열에 적용하느 냐에 따라 천차만별• 문자열을 다양한 길이로 만들면서 검사해야
  • 벤치마크 시 참고할 것• 정규 표현식 성능은 어떤 문자열에 적용하느 냐에 따라 천차만별• 문자열을 다양한 길이로 만들면서 검사해야• 역추적 폭주 예상이 중요 • 부분적으로 일치하는 긴 문자열로 시험
  • 효율성을 올리는 더 많은 방법• 실패할 거라면 되도록 일찍 실패하게 만드십시오• 단순하고 꼭 필요한 토큰으로 시작하십시오• 수량자를 붙인 패턴과 그 뒤에 있는 토큰을 배타적으로 만드십시오• or 연산자를 줄이고, 써야 한다면 적용 범위를 줄이십시오• 캡처하지 않는 그룹을 사용하십시오• 재사용할 텍스트를 캡처해서 후처리를 줄이십시오• 필수적인 토큰을 드러내십시오• 적합한 수량자를 쓰십시오• 정규 표현식을 변수에 할당해서 재사용하십시오• 복잡한 정규 표현식을 간단한 조각으로 나누십시오
  • 효율성을 올리는 더 많은 방법• 실패할 거라면 되도록 일찍 실패하게 만드십시오• 단순하고 꼭 필요한 토큰으로 시작하십시오• 수량자를 붙인 패턴과 그 뒤에 있는 토큰을 배타적으로 만드십시오• or 연산자를 줄이고, 써야 한다면 적용 범위를 줄이십시오 [^”rn]* ⇏ .*?• 캡처하지 않는 그룹을 사용하십시오• 재사용할 텍스트를 캡처해서 후처리를 줄이십시오• 필수적인 토큰을 드러내십시오• 적합한 수량자를 쓰십시오• 정규 표현식을 변수에 할당해서 재사용하십시오• 복잡한 정규 표현식을 간단한 조각으로 나누십시오
  • 효율성을 올리는 더 많은 방법• 실패할 거라면 되도록 일찍 실패하게 만드십시오• 단순하고 꼭 필요한 토큰으로 시작하십시오• 수량자를 붙인 패턴과 그 뒤에 있는 토큰을 배타적으로 만드십시오• or 연산자를 줄이고, 써야 한다면 적용 범위를 줄이십시오• 캡처하지 않는 그룹을 사용하십시오 이것 대신 이걸 씁니다• 재사용할 텍스트를 캡처해서 후처리를 줄이십시오 cat|bat [cb]at• 필수적인 토큰을 드러내십시오 red|read rea?d• 적합한 수량자를 쓰십시오 red|raw r(?:ed|aw)• 정규 표현식을 변수에 할당해서 재사용하십시오• (.|r|n) [sS] 복잡한 정규 표현식을 간단한 조각으로 나누십시오
  • 효율성을 올리는 더 많은 방법• 실패할 거라면 되도록 일찍 실패하게 만드십시오• 단순하고 꼭 필요한 토큰으로 시작하십시오• 수량자를 붙인 패턴과 그 뒤에 있는 토큰을 배타적으로 만드십시오• or 연산자를 줄이고, 써야 한다면 적용 범위를 줄이십시오/^(ab|cd)/ ⇏• 캡처하지 않는 그룹을 사용하십시오 /(^ab|^cd)/• 재사용할 텍스트를 캡처해서 후처리를 줄이십시오• 필수적인 토큰을 드러내십시오• 적합한 수량자를 쓰십시오• 정규 표현식을 변수에 할당해서 재사용하십시오• 복잡한 정규 표현식을 간단한 조각으로 나누십시오
  • 효율성을 올리는 더 많은 방법• 실패할 거라면 되도록 일찍 실패하게 만드십시오• 단순하고 꼭 필요한 토큰으로 시작하십시오• 수량자를 붙인 패턴과 그 뒤에 있는 토큰을 배타적으로 만드십시오• or 연산자를 줄이고, 써야 한다면 적용 범위를 줄이십시오• 캡처하지 않는 그룹을 사용하십시오• 재사용할 텍스트를 캡처해서 후처리를 줄이십시오• 필수적인 토큰을 드러내십시오• “괴물같은 정규 표현식은 만들지 말자!!” 적합한 수량자를 쓰십시오• 정규 표현식을 변수에 할당해서 재사용하십시오• 복잡한 정규 표현식을 간단한 조각으로 나누십시오
  • 정규식으르 쓰지 않는 것이 좋을 때• 찾으려는 부분이 문자열의 어디에 위치하는지 미리 안다면• 문자열 메서드만으로 처리 가능 하다면endsWithSemicolon = /;$/.test(str);endsWithSemicolon = str.charAt(str.length - 1) == ";";
  • 3 문자열 트리밍• ECMAScript 5 : String.prototype.trim• 정규 표현식 최적화 예제 단골
  • 정규식으로 트리밍 구현// trim 1if(!String.prototype.trim) { String.prototype.trim = function() { return this.replace(/^s+/, "").replace(/s+$/, ""); }}// 새 메서드를 테스트합니다.// 문자열 앞 공백에 탭(t) 문자와 줄바꿈(n) 문자를 넣었습니다.var str = " tn test string ".trim();alert(str == "test string"); // "true"
  • 정규식으로 트리밍 구현// trim 2String.prototype.trim = function() { return this.replace(/^s+|s+$/g, "");} • or 연산자의 두 옵션을 문자열의 모든 위치에서 시도
  • 정규식으로 트리밍 구현// trim 3String.prototype.trim = function() { return this.replace(/^s*([sS]*?)s*$/, "$1");} • 게으른 수량자(*?) 때문에 필요 없는 역추적이 많이 발생
  • 정규식으로 트리밍 구현// trim 4String.prototype.trim = function() { return this.replace(/^s*([sS]*S)?s*$/, "$1");} • 탐욕적 수량자로 변경해도 성능 향상 • 모든 문자에 일치하는 클래스를 탐욕적 수량자로 반복할 경 우 특별한 최적화 (FF, Opera 9 제외)
  • 정규식으로 트리밍 구현// trim 5String.prototype.trim = function() { return this.replace(/^s*(S*(s+S+)*)s*$/, "$1");} • 지금까지 예시 중 가장 느림 • 내부 그룹이 한번에 한 단어씩 수량자 중첩 상태
  • 정규식 없이 트리밍 구현// trim 6String.prototype.trim = function() { var start = 0, end = this.length - 1, ws = " nrtfx0bxa0u1680u180eu2000u2001u2002 u2003u2003u2004u2005u2006u2007u2008u2009 u200au200bu2028u2029u202fu205fu3000ufeff"; while(ws.indexOf(this.charAt(start)) > -1) { start++; } while(end > start && ws.indexOf(this.charAt(end)) > -1) { end--; } return this.slice(start, end + 1);}
  • 정규식 없이 트리밍 구현• 정규식은 중간에 문자를 고려하지 않고 맨 뒤 로 건너뛸 수 없음• 이 경우 두 번째 while 문이 문자열 맨 뒤에서 시작• 앞뒤 공백의 길이가 길면 성능 저하
  • 장점만 취한 해결책// trim 7String.prototype.trim = function() { var str = this.replace(/^s+/, ""), end = str.length - 1, ws = /s/; while(ws.test(str.charAt(end))) { end--; } return str.slice(0, end + 1);}
  • 결과
  • 결과
  • 4 요약• 문자열을 매우 많이 합치거나 큰 문자열을 합칠 때 인터넷 익스플로러 7과 이전 버전에서 무난한 성능을 내 려면 배열 병합이 유일한 방법입니다.• 인터넷 익스플로러 7과 이전 버전을 지원할 필요가 없다면 문자열을 합치는 방법 중 가장 느린 배열 병합을 쓸 필요는 없습니다. 단순한 + 연산자와 += 연산자를 쓰고 불필요한 중간 단계의 문자열을 없애십시오.• 역추적은 정규 표현식의 기본적인 구성 요소지만 비효율의 원인이 될 때가 잦습니다.• 보통은 일치하는 것을 빠르게 찾아냈을 정규 표현식도 역추적이 폭주하면 느리게 동작하며 부분적으로 일 치하는 문자열에 적용했을 때는 브라우저를 멈추게 할 수 있습니다. 인접한 토큰을 상호배타적으로 만들고, 중첩된 수량자가 같은 부분에 일치하지 않게 만들고, 룩어헤드를 최소 그룹처럼 동작하게 해서 불필요한 역 추적을 없애면 이런 문제를 피할 수 있습니다.• 일치하는 부분을 빨리 찾을 수 있게 만들고 일치하지 않는 부분에서 시간을 덜 소비하게 하는 방법이 여러 가지 있습니다 (“정규 표현식의 효율성을 올리는 더 많은 방법”을 보십시오).• 정규 표현식이 항상 최선의 수단인 것은 아니며 특히 리터럴 문자열을 찾으려 할 때는 정규 표현식을 쓰지 않아도 됩니다.• 여러 가지 방법으로 문자열의 앞뒤 공백을 잘라낼 수 있지만 두 개의 단순한 정규 표현식을 써서 하나는 문 자열 앞의 공백문자를 제거하고 다른 하나는 문자열 뒤의 공백문자를 잘라내도록 하면 간결한 코드로도 문 자열의 길이나 구성에 구애받지 않고 다양한 브라우저에서 효율적이게 할 수 있습니다. 반복문을 써서 문자 열의 맨 뒤에서부터 공백 아닌 마지막 문자까지 거슬러 올라가게 하거나 이 방법을 정규 표현식과 결합하면 문자열의 전체 길이에 별 영향을 받지 않습니다.
  • 4 요약• 문자열을 매우 많이 합치거나 큰 문자열을 합칠 때 인터넷 익스플로러 7과 이전 버전에서 무난한 성능을 내 려면 배열 병합이 유일한 방법입니다.• 인터넷 익스플로러 7과 이전 버전을 지원할 필요가 없다면 문자열을 합치는 방법 중 가장 느린 배열 병합을 쓸 필요는 없습니다. 단순한 + 연산자와 += 연산자를 쓰고 불필요한 중간 단계의 문자열을 없애십시오.• 역추적은 정규 표현식의 기본적인 구성 요소지만 비효율의 원인이 될 때가 잦습니다.• 보통은 일치하는 것을 빠르게 찾아냈을 정규 표현식도 역추적이 폭주하면 느리게 동작하며 부분적으로 일 치하는 문자열에 적용했을 때는 브라우저를 멈추게 할 수 있습니다. 인접한 토큰을 상호배타적으로 만들고, 중첩된 수량자가 같은 부분에 일치하지 않게 만들고, 룩어헤드를 최소 그룹처럼 동작하게 해서 불필요한 역 추적을 없애면 이런 문제를 피할 수 있습니다.• 일치하는 부분을 빨리 찾을 수 있게 만들고 일치하지 않는 부분에서 시간을 덜 소비하게 하는 방법이 여러 가지 있습니다 (“정규 표현식의 효율성을 올리는 더 많은 방법”을 보십시오).• 정규 표현식이 항상 최선의 수단인 것은 아니며 특히 리터럴 문자열을 찾으려 할 때는 정규 표현식을 쓰지 않아도 됩니다.• 여러 가지 방법으로 문자열의 앞뒤 공백을 잘라낼 수 있지만 두 개의 단순한 정규 표현식을 써서 하나는 문 자열 앞의 공백문자를 제거하고 다른 하나는 문자열 뒤의 공백문자를 잘라내도록 하면 간결한 코드로도 문 자열의 길이나 구성에 구애받지 않고 다양한 브라우저에서 효율적이게 할 수 있습니다. 반복문을 써서 문자 열의 맨 뒤에서부터 공백 아닌 마지막 문자까지 거슬러 올라가게 하거나 이 방법을 정규 표현식과 결합하면 문자열의 전체 길이에 별 영향을 받지 않습니다.
  • 주관적인 요약• 모던 브라우저는 충분히 빠르다. (즉, 하위 브 라우저에서 효율성 테스트면 충분할지도)• 정규 표현식 동작 과정과 역추적 정도는 알고 있어야 한다.• 정규 표현식이 최선의 수단은 아니다.