c' 글2.'.스 크락포드 ï. A~T . i 응 l 자바스크립트 언어의 정수! 뀔1글라스크락포드의 자tl}까、큐-랩틀 흘팩잠 7}흘l 亡 더글라스 크락포드 저 메 흰빛 P!1 패!, o~l VeryPDF Demo | 김명신 역 0 ’REILLY@ lE 튿:l5!r.!!IIii1섭.l.-.e‘~. , 자바스크립트 핵심 가이드 JavaScript VeryPDF Demo The G ood Parts |표지설명| 이 책의 표지에 있는 곤충은 플레인 타이거 나비입니다(Danaus chrysippus) 아시아 외부 지 역에서는 아프리카 황제 나비로도 잘 알려져 있습니다. 이 나비는 밝은 오랜지 색 날개 위에 여섯 개의 검은 접과 줄무늬가 특징인 중간 크기의 나비입니다. 플레인 타이거 나비의 아름다움은 매력적인 요소이지만 다른 한편으로는 죽음을 부르는 요소입 니다- 유충 단계 에서 이 나비는 새들에게 독이 되는 성분을 섭취합니다 플레인 타이거의 화려한 색에 사로즙랩 이를 잡아먹은 새는 반복해서 토하게 되고 심지어는 죽을 수도 있습니 다 만약 이 나비를 잡아먹은 새가 살아남게 된다면 이 새 는 다른 새들 에게 우아하고 유유자적하며 지면 가까이 나는 이 곤충을 피하도록 알렬 것입니다- 더글라스 크락포드의 자바스크립트 핵심 가이드 지은이 | 더글라스 크락포드 옮긴 0 1 1 김영신 펴낸 01 1 김태헌 펴낸곳 | 한빛 미디어(주) 주 소 | 서울시 마포구 앙화로 7 길 83 한빛 미디어 (주) IT출판부 전 화 I IT전문서팀 02)325-D984. 영업 1 팀 02)336-7114 팩 스 102)336-7124 등 록 1 1 999 년 6월 24일 제 1 0- 1779호 초판 빌썽 12008년 9월 29일 2쇄 발행 12011 년 9월 7일 정 가 1 22.000원 1S B N 1 978-89-79 14-598- 4 93560 기 획 | 서형절 VeryPDF Demo 이 책에 대한 의견을 주시 거나 오탈자 및 잘못된 내용의 수정 정보는 한빛미디어(주)의 흩페이지나 아래 이메일로 연락 주십시오 잘못된 책은 구입하신 서점에서 교환해 드립니다. | h!tp://WWW hanb c。 kr ask@hanb.co.kr Copyright @ 2008 HANBIT Media. Inc Authorized translation Korean 01 the English edition 01 JavaScript:The Good Parts @2008 0 ’Reilly Media, lnc. This translation is to be published and sold by permission 01 。’ Reilly Media. Inc .• the owner 01 all rights to publish and sell the same 이 잭의 효택어판 저작권은 오라일리 사와 독점 계약에 의해 한빛미디어(주)에 있습니다. 저작권법에 의해 효택 내에서 보호를 받는 저작물이므로 무단 복제 및 무단 전재를 금합니다. “〉 繼 빼뼈 Ajax의 등장으로 자바스크립트의 중요성은 이전보다 훨씬 강조되고 있습니다 하 지만 Ajax를 설명하는 책은 수없이 나왔음에도 자바스크립트의 본질에 대해 이야 기하는 책은 거의 없었던 것이 사실입니다. 다행인 것은 최근 들어 그러한 책들이 하나 둘씩 선 을 보이고 있다는 것이며 이 책도 그 중에 하나입니다. 자바스크립트계의 요다 스승으로 불리고 있는 더글라스 크락포드가 쓴 이 책은 자 바스크립 트에 대한 혜안을 제 공합니다. 자바스크립트를 많이 접해 보지 않았거나 가볍게 여기고 있던 분이라면 ‘혁 자바스크립트가 이렇게 심오했나!’ 하는 생각을 할 것입니다 이 책은 자바스크립트 제다이 기사로 인도하는 비급이라고 할 수 있 습니다 무공 비 급들 이 항상 그렇듯이 이 책의 내용은 쉽지 않습니다, 하지만 저자도 이 책 에서 얘기하고 있는 것처럼 반복해서 읽고 온전히 이해한다면 그 노력은 결코 헛 되지 않을것입니다 많은 제다이 기사 탄생 을 기대해 봅니다. VeryPDF|주의사항 Demo ! 이 책의 부록은 말 그대로 부록이 아니라 반드시 읽어야 하는 이 책의 주요 내용입 니다 꼭 부록까지 다 읽으세요 |감사의 글 | 제 행복의 근원 인 우리 가족과 너무도 교정을 잘 해주신 한빛미디어댄 서형철 대 리님께 감사드립 니다. 2008년 9월 김명신 3 魔”關’ ” 만약에 여러분의 비위에 거슬린다연, 이것이 곧 저회의 소원이외다. 여러분의 비위를 거슬리 려고 한 것은 아니고, 저회의 소원인 즉 서투른 솜씨를 보이자는 것이고 이것이 곧 저희들의 진정한동기외다. - 윌리엄 셰익스피어, 한여름 밤의 꿈 이 책은 자바스크립트 프로그래밍 언어에 관한 책입니다. 이 책의 목적은 자바스크 립트를 우연한 기회에 접하였거나 이에 대해 호기심이 생겨 탐험하고자 하는 프로 그래머들을 위해 쓰여졌습니다. 또한 이 책은 이전에 자바스크립트를 사용해 본적 이 전혀 없으면서 이제 막 자세히 알아보려고 하는 프로그래머를 위해서도 집필되 었습니다. 자바스크립트는 놀라울 정도로 강력한 언어입니다. 기존의 언어들과 조 금은 다른 특성들이 있지만, 그리 어렵지 않게 익힐 수 있습니다. VeryPDF필자의 Demo목적은 여러분이 자바스크립트식으로 생각할 수 있는 힘을 갖게 돕는 것입 니다 이 책을 통해서 자바스크립트라는 언어가 제공하는 기능들을 보여드렬 것이 며, 기능들을 잘 조합해서 사용하는 방법을 찾는 길로 여러분을 안내할 것입니다. 이 책은 참고용으로 쓰여진 것이 아닙니다. 즉 언어에 대한 모든 명세와 특성을 망 라하지 않으며 여러분이 후에 알 필요가 있을지도 모르는 모든 사항을 담고 있지 도 않습니다. 그러한 내용들은 온라인 상에서 쉽게 찾을 수 있을 것입니다. 대신에 이 책은 정말로 중요한 사항만을 포함하고 있습니다. 4 이 책은 초급자를 위한 책이 아닙니다. 앞으로 언젠가 저는 ]avaScrip t: The First Parts 라는 제목으로 초급자를 위한 책을 쓰고 싶습니다. 하지만 지금 이 책은 아닙 니다 또한 Ajax나 웹 프로그래밍에 관한 책도 아닙니다 이 책은 웹 개발자라면 반 드시 숙지해야 될 자바스크립트에만 온전히 초점을 맞추고 있습니다. 이 책은 분량이 적지만 그 내용에 있어서는 어 느 책보다도 깊 이가 있습니다. 다양 한 내용들이 잘 정제되어 있어서 조금 어려울 수도 있고, 이해가 잘 안 돼서 몇 번 을 다시 읽게 될 수도 있습니다 하지만 실망하지 않기 바랍니다, 그 노력의 결과는 분명히 달것입니다 |감사의글| 수많은 오류를 적절히 지적한 검토자 분들에게 감사드립니다. 인생에서 자신의 실수를 적절히 지적해주는 현명한 분들과의 교류보다 더 나은 것은 거의 없다고 생각합니다 특히 자신의 잘못 이 여러 대중에게 알려지기 전에 미리 검토 받을 수 있다는 것은 더욱 좋은 일입니다. Steve Souders , Bill Scott , ]ulien LeComte , Stoyan Stefanov , Eric Miraglia , Elliotte Rusty Haro ld 에게 진심으로 감사드립 니다 VeryPDF Demo 자바스크립트의 깊은 곳 에 있는 좋은 점들을 찾도록 도와준 일렉트릭 커뮤니 티 사와 스 테이 트 소프트웨어서 일하는 분들께 감사를 전합니다. 특히 Mornin 쌀 tar , Chip Randy Farmer , ]ühn La , Mark Miller , Scott Shattuck , Bill Edney 에게 는 더욱 감사드립니다. 제가 몸담고 있는 야후!에도 감사드립니다. 저에게 이 책을 집필할 수 있는 시간 을 주었으며 최상의 작업 공간을 제공했습니다. 아울러 과거와 현재의 Ajax Strike Force 팀 모든 분께도 감사드립니다 또한 오라일리 미디어에도 감사드리며 특 5 히 모든 작업이 원활히 진행되도록 도와준 Mary Treseler , Simon St.Laurent , Sumita Mukherji에게 감사드립니다. Li sa Drake 교수님에게 특별한 감사를 전합니다. 그리고 ECMAScript를 더 냐은 언어로 만들기 위해 고군분투하고 있는 ECMA TC39 구성원 여러분에게도 감사하 고싶습니다. 마지막으로 세계에서 가장 많은 오해를 받고 있는 프로그래밍 언어의 설계자인 Brendan Eich에게 감사합니다. 만약 그가 없었다면 이 책은 나오지 못했을 것입 니다. VeryPDF Demo 6 짧 빼빼 ) 딴l 자바스크럽트의 좋은 점들 01 I왜 자바스크럽트인가? 02 I 자바스크럽트 분석 03 I 예제 테스트를 위한 간단한 준비 lÐ. 자바스크럽트의 좋은 문법 들 11 mQ MH n 19 01 I 공백 (whitespoce) 02 I 이큼 03 I 숫자 (Nu mbers) 23 04 I 문자열 (Strings) 24 05 I 문장 (Sto tements) 26 표현식 (Express ions) 33 07 I 리터렬 (L뼈 ro ls) 36 08 I 함수(F unct ion s) 37 VeryPDF Demo06 I (Nomes) m 객처l 21 39 객 체 리터럴 03 I 속성값의 갱신 갱 02 I 속성값읽기 ”% 띠 01 I 20 7 04 1 참조 43 05 1 프로토타입 (Prototype) 43 06 1 리플렉션 (ref1ection) 45 071 열 거 (Enumeration) 46 08 1 삭제 47 09 1 최소한의 전역 변수 사용 47 톨l 함수 49 0 1 1 함수객체 49 02 1 함수리터렬 03 1 호출 51 04 1 인수 배 열 (arguments) 57 05 1 반환 58 06 1 예외 58 07 1 기본타입에 기응 추가 59 08 1 재귀적 호출 62 09 1 유효범위 (Scope) 65 101 클로저 (closure) 66 11 1 콜백 71 12 1 모율 72 13 1 연속 호출(Cascade) 75 14 1 커 링 (Curry) 76 VeryPDF Demo15 1 메 모이제이션 (memoization) 78 50 B 상속 01 1 의사 클래스 방식 (Pseudoclassica l) 02 1 객체를 기술하는 객체 (Object 03 1 프로토타엽 방식 04 1 함수를 사용한 방식 05 1 클래스 구성을 위한 부속품 Specifiers) mιmα∞ ω 8 81 % % m.배열 99 배열 리터렬 100 속성 101 011 02 1 length 03 1 삭제 103 04 1 열 거 104 05 1 객체와 배열의 혼동 104 06 1 배열의 메소드 106 07 1 배열의 그기와 차원 108 맏i 정큐표현식 111 01 1 예제 02 1 정규 113 표현식 객처1 생성 03 1 구성요소 120 122 멘깅l 메소드 131 믿i 스타일 157 m 163 아름다운 속성에 대한 단상 VeryPDF Demo 부록 A I 나보지만 사용해야 하는 부분들(Awful parts) 나쁜 점들 167 부록 81 부록 c JSLin t 193 부록 D I 구문 211 부록 E 1 JSON 1 찾아보 기 다이어 그램 181 223 237 9 VeryPDF Demo 활應웰 、 ’ C.H.A.P.T.E.R.I 자바스크럽트ζl 좋승 캠들 . 나는 마력 같은 건 없는 사람이요. 본래 타고난 좋은 점 (good ports)이 여성들에게 매력이 있는 거겠지요 - 윌리엄 셰익스피어, 윈저의 영랑한 아낙네들 휴뺏꺼 .. 초보 프로그 래머 시절에 필자는 새로운 프로그 래밍 언어를 사용 할 때 향상 언어의 모든 기능을 다 익혀서 사용하려고 노력했습 니다 (여러분도 경험해서 알겠지 만) 그렇게 하는 것 이 실력을 과시하는 것이라고 생각했고 또한 그렇게 익혀서 사용한 기능들은 모두 다 제대로 동작할 것이라고 믿었습니다 VeryPDF 하지만 Demo 결국 알 게 된 것은 그 기능들 중에 일부는 득보다 실이 많디눈 것이었습니 다. 일부 기 능은 제대 로 정의되지 않은 경우도 있었고, 다른 쪽으로 이식을 할 때 문제 를 일으키는 기능들도 있었습니다. 그리고 어떤 요소들은 수정을 어렵게 하거 나 가독성이 떨 어지게 했고 심지어 어떤 것 들은 오류가 발생할 확률이 높고 복잡 한 방법으로 프로그 래 밍해 야지만 사용할 수 있었습니다 그뿐만 아니라 어떤 기 능 들은 언어의 구조에 문제가 있는 경우도 있었고, 언어를 고안한 사람이 실수를 한 경우도있었습니다. 자바설립트으l 좋은 점들 | II 대부분의 프로그래멍 언어에는 좋은 점 (good parts) 과 나쁜 점 (bad parts) 이 있습 니다. 오랜 프로그래밍 경험으로 언어의 좋은 점만을 사용하고 나쁜 점은 사용을 자제함으로써 좀더 좋은 프로그래머가 될 수 있다는 것을 알게 되었습나다. 결국, 요점은 어떻게 하면 나쁜 점을 피해서 좋은 결과를 얻느냐는 것입니다. 표준을 제정히는 위원회가 언어의 나쁜 점들을 제거하기는 어렵습니다. 왜냐하면 위원회가 나쁜 점을 제거하게 되는 경우 기존에 그 나쁜 점을 사용하여 개발된 프 로그램들에 영호탤 미치기 때문입니다. 그러므로 위원회는 보통 기존의 불완전함 위에 더 많은 기능을 추가하는 것 외에는 힘이 없습니다. 설상가상으로 새로 추가 한 기능들이 기존 기능들과 조화를 이루지 못하는 경우도 있기 때문에, 언어의 나 쁜 점이 가중되는 결과를 낳기도 합니다. 하지만 다행인 것은 언어의 모든 기능과 명세가 어떻든 간에 그 기능들 중에서 자 신만의 부분집합을 지정할 수 있다는 것입 니다. 우리는 전적으로 언어의 좋은 점만 을 사용함으로써 좀더 나은 프로그램을 작성할 수 있습니다. 자바스크립트는 연구실에서 좀더 좋게 정련하는 과정을 거치지 못한 체 세상으로 나왔지만 출현하자마자 단기간에 브라우저 전체에 채택됐습니다. 그러나 기억할 점은 자바스크립트의 유명세는 프로그래밍 언어로서의 품질과 별개의 문제였다는 것입니다. 다행히도, 자바스크립트는 좋은 점 (good parts) 이 상당히 많습니다. 좋은 의도와 실수들 더미에 묻혀있는 아름답고 우아하며 매우 표현적인 특성이 있습니다. 자바 VeryPDF Demo 스크립트의 진정한 속성들은 자바스크립트는 별 볼일 없고 기능 없는 장난감에 불 과하다’는 지배적인 의견 때문에 수년 동안 감춰져 있었습니다. 이 책을 집필하게 된 의도가 이 부분에 있습니다. 바로 동적 언어로서 두드러진 특성을 지닌 자바스 크립트의 장점들을 부각하기 위해서입니다. 이 책에서는 자바스크립트의 진정한 본성을 드러내지 못하는 우아하지 않은 기능들을 모두 제거해 버렸습니다. 이 책에 서 제시하는 정제된 언어의 부분집합은 보다 신뢰할 수 있고 읽기 편하며 유지가 용이한 좋은 언어적 특성을 나타낼 것입 니다 뼈 「」 1 2. 1 4 이 책에는 자바스크립트의 모든 것이 담겨 있지 않습니다. 그래서 간간히 피해야 할 나쁜 점들을 언급하기는 하지만 전적으로 자바스크립트의 좋은 점에만 초점을 맞출 것입니다. 여기서 기술하는 부분집합은 크던 작던 규모에 상관 없이 신뢰할 수 있고 가독성이 좋은 프로그램을 작성하는데 사용할 수 있습니다. 또한 좋은 점 (good parts) 에만 초점을 맞춤으로써 언어를 익히는 시긴도 단축할 수 있고, 프로 그램의 견고함도 높일 수 있으며 종이도 아낄 수 있습니다. 아마 좋은 점 (good par연)만을 배움으로써 얻을 수 있는 최대의 이점은 나쁜 점을 잊어야 하는 수고를 덜 수 있다는 것입니다. 나쁜 패턴을 잊어버리는 것은 쉽지 않 습니다. 잊어버리려고 시도하면 대부분은 심한 저항에 부딪히게 됩니다 때때 로 프 로그래밍 언어 를 보다 쉽게 가르치기 위해서 부분집합만을 사용히는 경우가 있습 니다, 하지만 이 책에서는 그런 초보용 부분집합이 아니라 전문가를 위한 자바스크 립트의 부분집합을 다룹니다 01 I 왜 자바스크럽트인가? 자바스크립트는 웹 브라우저의 언어이기 때문에 세계에서 가장 유명하고 중요한 언어 중 하나입니다. 하지만 그와 동시에 가장 무시 당하고 있는 언어 중에 하나이 기도 합니다 브라우저의 API라고 할 수 있는 DOM (Document Object Model)은 아주 형편없는데 거기에 편승하여 자바스크립트도 부당한 비난을 받고 있습니다. VeryPDF DOM은 Demo 어떠한 언어 로 다루든지 용이하지 않습니다. DOM은 서툴게 정의됐으며 그에 따라 그 구현도 제 각각입니다 이 책에서는 DOM에 관해 아주 적은 부분만 을 언 급합니다 아마 DOM에 관한 좋은 점만을 모아 놓은 책을 집필핸 것은 매 우 어려운 도전일 것입니다 자바스크립트는 여타 다른 언어틀과 다른 점이 많기 때문에 매우 저 평가돼 있습 니다 만약 여러 분 이 다른 언어들에 익숙한 상태인데 오로지 자바스크립트만 지원 하는 환경에서 프로그 래멍 을 해야 하는 상황에 처한다면 , 당연히 자바스크립트만 을 사용해야 할 것이며 이로 인해 무척 짜증이 날 것입니다. 이러한 상황에 처하는 자바섣럽트의 좋은 정들 I 13 대부분의 사람은 일단 자바스크립트를 알아보려는 노력조차 하지 않습니다. 그러 다가 자신들이 대신 사용했으면 하는 언어와 매우 다르다는 점에 놀라고 차별하기 시작합니다. 자바스크립트의 놀라운 점은 언어 자체에 대해 많이 모르거나 심지어는 프로그래 밍에 대해 잘 모르더라도 원하는 작업을 할 수 있다는 것입니다. 이를 볼 때 자바스 크립트는 놀라운 표현력을 가진 언어입니다. 하지만 여러분이 무엇을 하고 있는지 알고 있을 때 자바스크립트는 더 큰 힘을 발휘합니다 프로그래밍은 어려운 비즈니 스기 때문에 결코 무지한 가운데 진행해서는 안됩니다. 02 I 자바스크럽트 분석 자바스크립트는 몇몇의 매우 좋은 아이디어와 몇몇의 나쁜 (그것도 아주) 아이디 어에 기초하여 만들어졌습니다 매우 좋은 아이디어에는 함수, 느슨한 타입 체크, 동적 객체, 표현적인 객체 리터럴 표기볍 등이 있습니다. 그리고 대표할 만한 나쁜 아이디어는 프로그래밍 모델이 전 역변수에 기초하고 있디는 것입니다. 자바스크립트의 함수는 어휘적 유효범위를 가진 일급 객체 (first-class object)1 입 니다. 또한 주류가 된 첫 번째 람다 Oambda)2 언어며, 좀더 깊이 들어가면, 이름처 럼 자바에 가깝기보다는Lisp VeryPDF Demo 언어 그리고 Scheme 언어와더 많은공통점이 있습 니다. 자바스크립트는 C의 옷을 입은 Lisp 이라고 할 수 있습니다. 놀라울 정도로 강력한 언어적 특징은 바로 이러한 특성에서 기인한 것입니다. 1 역자 주/ 언어상에 제약이 없는 객체를 일급 객체라고 합니다 즉 번수에 대입되거나 인수로 넘길 수도 있고, 반환값으로 사용하거나 연산 등에 사용하는데 전혀 제약이 없는 객체입니다 자바스크립트에서는 함수가 일급 객체이므로 이 모든 것 이 다 가능합니다 영문이지만 보다 자세한 내용은 http://en.wikipedia.org/wiki/First-class_object를 참고하세요 2 역자 주/ 람다는 Alonzo Church와 Stephen Cole Kleene의 람다 대수(La mbda calculus , http://en ,wikipedi a. org/ wikij La mbda_calculus 잠조)에서 유래한 것으로 익영 함수나 클로저 등을 정의하기 위한 표현식을 의미합니다 더 자세 한 사항은 니sp이나 파이씬에서 람다 부분을 찾아보기 바랍니다, 영문이지만 자세한 내용은 http://en.wikipedia.orgjwiki/ La mbda를 잠고하세요 14 I CHAPTER 1 오늘날 프로그래밍 언어 대부분은 강력한 데이터 타입 체크를 요구합니다. 이러 한 경향은 강력한 타입 체크를 해야 컴파일러가 컴파일 시간에 가능한 많은 오류 를 찾을 수 있다는 이론에 근거한 것입니다 오류를 가능한 빨리 찾아서 수정을 하 면 추후에 오류 발생으로 생기는 비용을 더 많이 줄일 수 있다는 생각입니다 자바 스크립트는 느슨한 타입 체크 언어입니다. 그래서 자바스크립트 컴파일러는 타입 오류를 찾을 수 없습니다. 이러한 점은 강력한 타입 체크를 하는 언어를 사용하다 가 자바스크립트로 넘어온 사람들에게는 놀라운 일일 수 있습니다. 하지만 강력한 타입 체크가 중요한 오류들을 효율적으로 제거하지 못한다는 것이 판명됐습니다. 그리고 경험에 의하면 강력한 타입 체크가 오류를 알려주기는 하지만 실제로 우려 하는 오류들은 알려주지 못합니다. 반면에 느슨한 타입 체크에서 발견한 것은 오류 찾기의 어려움이 아니라 자유로움입니다. 느슨한 타입 체크를 하는 언어를 사용하 면 복잡한 클 래 스 계층을 구성할 필요도 없으며, 원하는 대로 동작하도록 타입 캐 스팅과 씨름할 필요도 없습니다. 자바스크립트는 매우 강력한 객체 리터럴 표기법이 있습니다. 이 표기법을 사용하 면 단순히 필요한 요소들을 열거하는 방볍으로 객체를 만들 수 있습니다. 이러한 표기법은 유명한 데이터 교환 형식인 ]SON에도 영감을 주었습니다(JSON은 부록 E에서 자세히 알아봅니다). 자바스크립트에서 논란의 대상이 되는 기능은 프로토타입에 의한 상속입니다 자 바스크립트는 클 래 스가 필요 없는 객체 시스템이 있어서 특정 객체에 있는 속성들 을 다른 객체에 직접 상속할 수 있습니다. 이러한 특성은 매우 강력하지만 클래스 VeryPDF Demo 기반의 언어에 익숙한 프로그 래머에게는 친숙하지 않은 점입니다 만약, 여러분이 클래스 기반의 설계 패턴을 그 대로 자바스크립트에 사용하려고 한다면 아마 좌절 감을 느낄 것입니다. 하지만 자바스크립트가 제공하는 프로토타입의 특성을 배운 다면 이러한노력은분명 보상받을것 입니다. 자바스크립트는 몇몇 핵심 개념들 때문에 더 많이 비난을 받고 있습니다 좀 다르 긴 해도 핵심 개념의 대 부분은 좋은 선택이었습니다 하지만 특별히 잘못 선택된 점이 하나 있는데 그것은 전역변수에 근간을 두고 있다는 것입니다. 모든 컴파일 얄 택 바 자 E 15 단위에 있는 최상위 레벨의 변수들은 모두 전역객체 (global object) 라 불리는 공 용 이름 공간 (namespace) 에 위치하게 됩니다. 전역변수는 나쁘기 때문에 이러한 개념은 상당히 좋지 않다고 볼 수 있습니다. 그런데 이것이 자바스크립트의 근간을 이루는 것 중에 하나입니다. 그나마 다행인 것은 자바스크립트에는 이러한 문제를 완화시킬 수 있는 방법이 있다는 것입니다. 때때로 어쩔 수 없이 사용하는 자바스크립트의 나쁜 점들이 있습니다. 이렇게 피할 수 없는 필요악 같은 부분들은 이 책에서 나올 때마다 바로 언급할 것입니다. 또한 이런 부분들을 부록 A에 정리했습니다. 피할 수 없는 나쁜 부분들이 있기는 하지 만, 우리는 이 책으로 인해 부록 B에서 알려주고 있는 꼭 피해야 할 자바스크립트 의 나쁜 점들은 대부분 피하는데 성공할 것입니다 만약 여러분이 이 책에서 다루 지 않은 더 많은 나쁜 점을 그 사용법까지 자세히 알고 싶다면 여타 다른 자바스크 립트 책을 만나보기 바랍니다. 자바스크립트(또는 ]Script)를 정의하고 있는 표준은 「π1e ECMAScript Programming Language third EdtionJ (http :j /www.ecmainternational.org/publications/files/ ecma - s t/ECMA -262.pdf)입니다. ECMAScript는 나쁜 부분을 포함하기 때문에 이 책에서는 언어 전체를 기술하지 않습니다. 즉 전체를 총망라하여 기술하지 않고 위 험한 부분들을 피해서 기술하고 있습니다. 부록 C에서는 ]SLint라는 프로그래밍 툴을 설명합니다. 이 툴은 자바스크립트 프로 그램을 분석하여 포함된 나쁜 점들을 알려주는 자바스크립트 파서입니다. ]SLint는 보통 자바스크립트 VeryPDF Demo 개발에서 부족하기 쉬운 엄격한 수준의 분석 결과를 제공합니 다 그러므로 이 툴의 분석에서 나쁜 점이 보고되지 않았다면 자바스크립트의 좋은 점만을 사용해서 프로그래밍됐다고 확신할 수 있습니다. 자바스크립트는 모순이 많은 언어입니다 자바스크립트에는 많은 오류가 있기 때 문에, ‘도대체 왜 자바스크립트를 사용해야 하지 ?’하고 생각할 수 있습니다. 이에 대한 답은 두 가지가 있습니다. 그 중 첫 번째는 선택의 여지가 없다는 것입니다. 웹은 애플라케이션 개발에 있어 중요한 플랫폼이며, 자바스크립트는 모든 브라우 16 빼 저에서 사용할 수 있는 유일한 언어입니다. 자바가 이 환경에서 실패한 것은 어쩌 1 L 변 불행한 일이라고도 볼 수 있습니다. 만약 자바가 실패하지 않았다면 강력한 타 입 체 크를 히는 클 래 스 기반의 언어를 원하는 이 들에게는 좋은 선택이 됐을 것입 니다 하지만 자바는 실패했고 자바스크 립트는 살아남아 번성했으며, 이는 자바스 크립트가 나름대로 옳았디는 하나의 증거이기도 합니다. 두 번째 답은 많은 부족한 변이 있기는 하지만 자바스크립트는 실제로 꽤 괜찮 다는 것입니다 자바스크립트는 매우 경량화돼 있으며 표현적 ( expressive ) 입니 다. 그리고 일단 언어 사용의 요령을 익히고 나면 함수형 프로그래밍 (functional pr ogramming) 이 꽤 재미 있다는 것을 알게 됩니다. 하지만 자바스크립 트라는 언어를 잘 사용하기 위해서는 이 언어의 한계점을 잘 알 아야 합니다. 이 를 위해 이 책에서는 자바스크립트를 용감하게 조각내서 좋은 점만 을 제 공할 것입니다 자바스크립트의 좋은 점 들 (good parts ) 은 나쁜 점들을 보상 하고도 남을 정 도로 충분한 가치가 있습니 다. 03 I 예제 테스트를 위한 간단한 준비 웹 브라우저와 텍스트 에디터만 있으면 자바스크립트 프로그램을 실행시킬 모든 준비가 끝난 것입니다. 먼저 다음 내용을 program.html 파일로 저장합니 다 < b ody>
 
< /html > 그런 다음같은폴더에 다읍의 내용을 program.Js 파일로저장합니다. d oc ument . writeln( ’ Hello , world l ’ ) ; 자바설립트으l 좋은 점들 | 17 이제 결과를 보기 위해 program.html 파일을 브라우저로 불러와서 결과를 확인합 니다. 다음에 나오는 코드는 이 책 전체에서 새 로운 메소드를 정의할 때 두루 쓰이는 me thod라는 메 소드입니다. Fu n ction . prototype . method this . prototype[name ] f unction (name , func ) func ; return this ; 일단 눈여겨보기 바랍니다. 이 메소드에 대한 자세한 내용은 4장에서 살펴봅니다 VeryPDF Demo 爛 18 1 4 활뿔찮싹 、 자바스크럽트ζl 좋승 문볍들 내가 잘 아는 것 이 군. 오래 전 문법책 여1문에 서 읽은 시 구로군­ -윌리 얻 셰익스피어, 타이터스 앤드로니커스 이번 장에서 는 자바스크립트의 좋은 점 들 (good p arts) 에 해당하 흉g 는 문 법 을 살펴봅니다. 이 문법 들을 살펴봄으로써 언어가 어떻게 구성되었는지 빠르 게 확인 할 수 있습니다 각 문법은 철도 다이어그램으로 설명합 니다. 철도 다이어그랩 을 해석히는 방법은 간단합니다. • 왼쪽에서 시 작해서 트랙을 따라 오른쪽 끝으로 이동합니다. VeryPDF Demo · 오른쪽으로 가다보면 퉁근도형 안의 리터럴이나사각형 안에 있는설명 또 는 규칙을 만납니다 • 트 랙 을 따라가는 것이라면 어떠한 경로라도 유효합니다. • 트 래 을 따라가지 않는 경 로는 모두 무효입니다. • 양 끝에 세 로 막대 하나를 가진 철도 다이어그램은 한 쌍의 토큰 사이에 공백 (w hites p ace) 을 허용한다는 뜻 이며 , 세로 막대 두 개가 있는 경우는 그렇지 않다는뜻 입니다. 자바셜럽트으1 뽑 문법들 | 19 좋은 점 (good p없)만을 설명하는 이번 장의 문법은 자바스크립트 전체 문법보다 훨씬간단합니다. 01 I 공백 (whitespace) 공백 (whitespace) 줄끝문자를 제외한모든문자 *와/를제외한 모든문자 공백은 문자를 구분하는 형태나 주석의 형태를 취할 수 있습니다(즉, 주석 역시 공 백입니다) . 보통 공백은 별로 중요하지 않지만, 때때로 공백을 사용하지 않으면 하 토큰으로 VeryPDF나의 Demo 묶여버리는 문자들을 분리하기 위해서 필요합니다. 다음은 그 예입 니다 var that this ; 「 뼈 1. 역자 주/ 줄 끝’이라는 표현이 많이 나올 것입니다 줄 끝(줄 끝 문재은 우리가 흔히 생각하는 CRO I 나 LF 등을 의미합니다 그래서 ‘줄 끝’이라는 표현이 나오언 이린 의미로 생각하연 됩니다- 참고로 ECMASc ripl 영세에서 정의하고 있는 줄 종결자 (Une Terminators)에는 CR. LF 외에도 LS(Une Separalα). PS( Paragraph Separatα)가 있습니다‘ 20 4 var와 that 사이에 있는 빈 칸은 제거할 수 없습니다. 하지만 다른 빈 칸들은 제거해 도상관없습니다. 자바스크립트에서는 j* * j 형태의 블록 주석과 jj 형태의 한 줄 주석을 사용할 수 있습니다 주석은 프로그램의 가독성을 높이기 위해 충분히 사용되는 것이 좋습니 다. 주석을 달 때는 항상 코드에 대해 정확히 설명해야 합니다. 쓸모 없는 주석은 없느니만못합니다. 블록 주석을 달 때 시용하는 /* *j는 PL!I이라는 언어에서 비 롯된 것입니다. PL!I은 이 이상한 한 쌍을 주석을 위한 기호로 삼았는데 그 이유는 PL!I 프로그램에서는 문자열 리터렬을 제외하고는 이러한 조합이 거의 나타나지 않기 때문입니다. 하지 만 자바스크립트에서는 이러한 조합이 정규 표현식 리터럴에서도 나타날 수 있습 니다 그러므로 블록 주석 방법은 안전하지 않다고 볼 수 있습니다. 예를 들어 다음 과 같은 코드를 블록 주석으로 주석화하면 구문 오류가 발생합니다. /* var rm a =/a*/ . match (5); */ 그러므로 가능하면 /* * j를 사용하는 대신 jj를 사용할 것을 권합니다. 이 책에서는 jj만을 사용하고 있습니다. VeryPDF Demo 02 I 이름(Names) 이름 자바섣럽트으1 좋은 문볍들 | 21 이름 (name) 은 하나의 문자나 그 뒤를 이어서 하나 이상의 문자, 숫자, -가 붙는 문 자열로 문장, 변수, 매개변수, 속성명, 연산자, 라벨 등에 사용합니다. 다음에 나오 는 예약어들은 이름 (name) 이 될 수 없습니다. abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function got 。 if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var volatile void while with (이 목록에는 예약어에 꼭 포함할 것 같은 unde fined , NaN , Infinity 등은 없습 니다.) 여기에 열거된 예약어 대부분은 실제로 언어에서 사용하지 않습니다. 예약어는 변 VeryPDF Demo 수 이름이나 매개변수 이름으로 사용할 수 없습니다. 게다가 예약어는 객체 리터럴 의 속성명이나 객체의 속성을 나타낼 때 사용하는 마침표 다음에 사용할 수 없습 니다. 「 뼈 22 ‘/ 03 I 숫자(Numbers) 숫따똘웰-4=합μE란그 l 자바스크립트는 숫자형이 하나만 있습니다 내부적으로 숫자는 64비트 부동 소수 점 형식을 지닙니다. 이는 자바의 double 형과 같습니다. 대부분의 다른 언어와는 달리 자바스크립트에는 정수와 실수의 구분이 없습니다. 즉 l 과 10은 같은 값입니 다. 이러한 특성은 매우 편리합니다. short 형을 사용해서 오버플로우가 발생히는 일 등이 전혀 없으며, 단지 알아야 할 것은 숫자형이라는 것뿐입니다 결국 숫자형 때문에 발생히 는 오류 대부분을 피할 수 있습니다. f←키〕 니 Lc뭔) VeryPDF Demo 숫자 리터 럴 이 지수부분을포함하는 경우 이 숫자 리터럴의 값은 e 앞의 값에다 e 뒤의 값만큼 10을 제곱한 값의 곱이 됩니다. 그래서 100은 1e2와 같습니다. 읍수는 수 앞에 - 를 붙이면 됩니다. 자바스크립트의 좋은 문법들 23 NaN은 수치 연산을 해서 정상적인 값을 얻지 못할 때의 값입니다. NaN은 그 자신 을 포함해서 어떤 값하고도 같지 않습니다 그러므로 NaN인지 확인하려면 비교 구 문이 아니라 isNaN()이라는 함수를 사용합니다. 1.79769313486231570e+308 보다 큰 값은 Infinity로 나타납니다. 숫자는 메소드가 있습니다 (8장 참조) 자바스크립트의 Math라는 객체에 수치 계산 을 위한 메소드가 있습니다. 예를 들어 Math.floor (number ) 메소드는 수를 정수 로 변환할 때 사용합니다. 04 I 문자열 (Strings) “과 ₩ 그리고 제어문자를 제외한 모든유니코드문자 이스케이프된문자 “과 ₩ 그리고 제어문자를 제외한 모든유니코드문자 이스케이프된문자 VeryPDF Demo 문자열은 작은 따옴표나 큰 따옴표로 묶어서 나타내며, 따옴표 안에는 문자 0개 이 상을 포함합니다. \(백슬래시)는 이스케이프 문자입니다. 자바스크립트는 유니코 드가 16비트 문자 셋이었을 때 개발했기 때문에 자바스크립트 내의 모든 문자는 16비트 유니코드입니다. L 「 r 뼈 24 ‘/ 이스케이프된문자 큰따옴표 작은따옴표 역슬래시 슬래시 g/ 역스페이스 늪촉III드 LF CR 댐 4자리의 16진수 자바스크립 트에는 문자 타입이 없습니다. 그러므로 문자 하나를 나타내기 위해서 는 문자 하나만을 포함하는 문자열을 사용해야 합니다 이스케이프 시권스로 \나 따옴표, 제어문자처럼 일반 문자가 아닌 특별한 문자를 문자열에 삽입할 수 있습니다 \u로 시작하는 표기법은 유니코드 숫자값으로 문자 를나타낼수있습니다. A" \u0041 " VeryPDF Demo 문자열은 l e ngth 라는 속성이 있습니다 “ seven" .length 의 값은 5 입니다. 문자열은 변하지 않습니다(i mmutable) . 일단 문자열이 한번 만들어지면, 이 문자 열은 결코 변하지 않습니다. 하지만 여러 문자열을 + 연산자로 연결하여 새로운 문자열을 만들 수 있습니다 분리된 문자열이 + 연산자로 연결되든 그냥 문자열 하나든 문자들의 순서가 같으면 같은 문자열입니다. 그래서 다음의 예는 참 (true) 입니다 자바스크립트의 좋은 문볍들 25 ' c ’ + ’ a ’ + ’ t ’ --- ’ cat ’ 문자열은 메소드가 있습니다 (8장 참조) . ’ ca t ’ . toUpperC ase( 05 I ’ CAT ’ 문장(Statements) var 문 표현식 하나의 컴파일 단위에는 실행을 위한 문장들이 포함돼 있습니다 웹 브라우저에서 각각의 (script) 태 그는 컴파일되어 즉시 실행되는 하나의 컴파일 단위입니다. 령 커(linker)7} 없기 때문에 자바스크립트는 모든 문장을 공통적인 전역 이름 공간 (namespace) 에 한 데 몰아 넣습니다 전역변수에 관한 좀더 자세한 부분은 부록 A 에서셜명합니다 VeryPDF Demo var 문은 함수 내부에서 사용될 때 함수의 private 변수를 정의합니다. 빼 1 ι 26 드프 ;q ‘-'-0 표현식문장 벗어나는문장 try 문 if ~ 디 switch 문 while 문 for 문 d。문 switch 문 while 문 , for 문, do 문에는 break 문에서 사용할 수 있는 라벨을 선택 적으로 지정할 수 있습니다. 벗어나는문장 VeryPDF Demo break 문 return 문 throw 문 릅 문장들은 대개 위에서 아래로 순서대로 실행합니다. 이러한 실행 순서는 조건문 (if, switch) 이나 반복문 (while , for , do) 또는 실행 흐름을 벗어나는 문장 (break, re turn , throw) 이나 함수 호출로 변경할 수 있습니다. 때L 문장들 다굉 자바섣럽택 좋은 문법들 I 27 블록은 중괄호로 쌓인 문장들의 집합입니다. 다른 언어들과 달리 자바스크립트에 서 블록은 새로운 유효범위 ( scope) 를 생성하지 않습니다. 이러한 이유로 변수는 블록 안에서가 아니라 함수의 첫 부분에서 정의해야 합니다. if 문 Then r확관카 표현식 냉王렐4월7않그뉘 f 문은 표현식의 값에 따라 프로그램의 흐름을 변경합니다 then 블록은 표현식이 참 (true) 일 때 실행하며, 표현식이 거짓인 경우에는 else 블록을 실행합니다(물론 else 블록은 선택적입니다) . 다음은거짓에 해당하는값들입니다. • false 때 .n • undefined ·빈문자열‘’ · 숫자 0 • N aN 이 외의 모든 값은 참입니다 예를 들어 VeryPDF Demo 참입니다. switch 문 願 28 1 / ‘ true , 문자열 ‘f외se ’ , 모든 객체 등은 모두 switch 문은 다중 분기를 수행합니다. 이 문장은 표현식과 모든 case 문의 표현 식이 같은지를 비교합니다. 표현식의 결과값은 숫자일수도 있고 문자열일수도 있 습니다. 일치승}는 표현식을 찾으면 해당 case 절에 있는 문장들을 실행합니다. 만 약 일치히는 표현식을 찾지 못하는 경우에는 default 절의 문장들을 실행합니다 (default는 선택사항입니다) case 절 case 절은 하나 이상의 case 문을 포함합니다.case 절의 표현식은 꼭 상수일 필요 가 없습니다.case 절의 문장 마지막에는 다음 case 절로 넘어가지 않게 실행 흐름 을 벗어나는 문장을 사용해야 합니다 이를 위해 break 문을 사용할 수 있습니다. whíle 문 while 문은 단순한 반복 수행 문장입니다. 표현식이 참인 동안은 블록을 반복해서 실행하며, 표현식이 거짓이면 반복 수행은 끝납니다. lor 문 초기화 VeryPDF Demo 표현식문장 조건 표현식 증가 표현식문장 자바섣립트으l 뽑 문법들 I 29 for 문은 좀더 복잡한 반복문입니다. 이 실행문은 두 가지 형식으로 사용합니다. 일반적인 형식은 초기화, 조건, 증가리는 세가지 절로 제어하는 구조입니다(다이 어그램에서 볼 수 있는 것처럼 이 세가지 절은 모두 선택적입니다) . 먼저 초기화를 실행합니다. 보통 이 부분에서 반복 횟수를 제어하는 변수를 초기화합니다. 그 다 음에 조건 부분이 만족하는지를 검사합니다. 이 검사의 전형적인 형태는 반복 횟수 를 제어하는 변수가 조건에 만족하는지를 확인하는 것입니다. 만약 조건 부분이 생 략되면 참으로 간주합니다 조건 부분의 검사 결과가 거짓이면 반복을 종료합니다. 조건을 만족해서 블록을 한 번 실행하면 증가 부분을 실행하고 다시 조건 검사를 반복합니다. 또 다른 형식을 for 문의 형식은 객체의 속성 이름(또는 키)을 열거하는 것입니다(이러한 for in이라고 부릅니다) . 각각의 반복 실행마다 객체에 있는 각각의 속성 이 름을 변수에 할당합니다. 이 for in 형식은 보통 다음과 같이 objec t. hasOwnProperty( 변수) 메소드로 속성 이름이 실제로 객체의 속성 인지 아니면 프로토타입 체인 (prototype chain) 상에 있는 것인지를 확인하는 것이 필요합니다. for (myvar in obj) if (ob j .hasOwnProperty(myvar)) { VeryPDF Demo d。문 do 문은 표현식이 블록을 실행하기 전이 아니라 실행한 후에 검사된다는 점만 빼 면 while 문과 같습니다. 이러한 특성 때문에 do 문은 적어도 한 번 블록을 실행합 니다. L 뼈 r 30 ‘ ‘/ try 문 ,"""、 L I 따r 문은 블록을 실행하면서 블록 내에서 발생'Ô"}는 예외 상황을 포착합니다. catch 절은 예외 객체를 받는 새 로운 변수를 정의합니다 throw 문 throw 어는 문은 예외 를 발생합니다. 만약 throw 문이 따7 블록 안에 있으면 실행의 제 catch 절로 이 동합니다. 만약 throw 문이 일반적인 함수 내에 있다면 함수 호 출은 중단되고 함수를 호출한 따f 문의 catch 절로 실행 흐름이 이동합니다. 표현식 부분은 보통 n ame 과 message 라는 속성이 있는 객체 리터럴입니다 예외 를 포착한 곳에서 는 이 객 체 의 정보로 무엇을 수행할지 결정할 수 있습니다 뉴f략포고 { 표현식 | G내 return 문은 함수에서 호출한 곳으로 되돌아가는 역할을 합니다. 또한 이 문장은 반환값을 지정합니다. 표현식 이 지정되지 않으면 undefine d를 반환합니다. VeryPDF자바스크립트는 Demo 뉴G월D re turn 과 표현식 부분 사이에 줄 바꿈을 허용하지 않습니다. G키 break 문은 반복문이나 switch 문에서 흐름을 벗어나게 하는 역할을 합니다. 이 문장은 라벨 이 름을 취할 수 있는 데 라벨이 주어지면 라벨이 붙은 문장의 끝으로 이 동합니다 자바섣럽트의 촬 문법들 j 31 자바스크립트는 break와 라벨 사이에 줄 바꿈을 허용하지 않습니다. 표현식문장 표현식 세부지정( 또는[]) 세부지정( 또는[]) 표현식 문장은 값을 하나 이상의 변수나 객체의 속성에 할당하거나 메소드를 호출 하고 객체의 속성을 삭제할 수 있습니다 당 연산자를 동등 연산자인 연결합니다. VeryPDF Demo 뼈 32 1 / ‘ 연산자는 할당하는 데 사용합니다. 할 와 흔동해서는 안 됩니다 += 연산자는 더하거나 06 I 표현석 (Expressions) 표현식 전치연산자 이항연산자 호줄 세부지정( 또는[]) 세부지정( 또는 []) 가장 간단한 표현식은 리터 럴 값(문자열이나 숫자) , 변수, 내장값들 (true , false , null , undefine d , NaN, Infinity 등) , new 키워 드에 의한 호출 표현식, delete 키워 드 다음에 나오는 세부지정 표현식, 괄호로 쌓인 표현식, 전치 연산자 다음에 이어 지는 표현식 등입 니다. 그리고 그 외에도 다음과 같은 표현식이 있습니다. VeryPDF Demo · 이항연산자의 표현식 • ? 삼항 연산자의 표현식 . 호줄 • 세부지정 (. 또는 []) ? 삼항 연산자는 3개의 피연산자를 취합니다. 첫 번째 피연산자가 참이면 , 두 번째 피연산자가 값이 되지만, 첫 번째 피연산자가 거짓인 경우에 는 세 번째 피연산자가 값이 됩니다. 버닝 뽑 택 바 자 33 [표 2-1J 목록에서 상위에 있는 연산자일수록 우선 순위가 높습니다. 괄호를 사용 하면 일반적인 우선 순위를 변경하여 높은 우선 순위를 갖게 할 수 있습니다. 다음 은그예입 니다. 2 + 3 * 5 17 (2 + 3) * 5 2-1) 〔표 25 연산자 우선 순위 세부지정이나호출 []() delete new tYPE셔 +- ! */ % -/ (、 - ---」 ------ : -- 더하기/연결, 빼기 μ - - ι 」「 -> 단항연산자 곱하기, 나누기, 나머지 같지않음비교 --- 짧 .'i'-드드 논리적 -”” and 논리적 or ?· 삼항 전치연산자 피연산자의타입 숫자로지정 2 부정 논리적 not VeryPDF Demo typeof 연산자의 결과값에는 number , string , boolean , undefined , function , object 등이 있습니다. 피연산자가 배열이나 null이면 결과는 모두 object 인데 이 는 약간 문제가 있습니다 이 문제를 포함하여 typeof 연산자에 대한 자세한 부분 은 6장과부록 A에서 살펴봅니다. 2 역자 주/ + 는 피연산자가 숫자일 경우에는 크게 의미가 없거나 앙수를 명확히 나타내지만 피연산자가 숫자가 아닐 경우 에는 이를 숫자로 번환하는 역할을 합니다 숫자로 변환할 수 없을 경우에는 NaN을 반환합니다 -는 피연산자를 부정합니 다 즉 띠연산자가 음수이연 앙수로, 앙수이 연 음수로 변환합니다 「 뺨 」 배 r 34 ‘/ 연산자의 피연산자 값이 참이면 결 과값은 거짓이며 그 반대면 결과값은 참입 ! 니다. 이항연산자 논리적 or 나머지 큰 작은 + 연산자는 수를 더하거나 문자열을 연결합니다. 더하기 연산을 원하는 경우에는 반드시 피연산자 두 개가 모두 숫자여야 합니 다. / 연산자는 피연산자 두 개가모두 정수형이어도 결과값이 실수일 수 있습니 다, && 연산자는 첫 번째 피연산자가 거짓일 경우 첫 번째 피연산자의 값을 취하고, 그렇지 않은 경우에는 두 번째 피연산자 값을 결과값으로 취합니다. 11 연산자는 &&와 반대로 첫 번째 피연산자가 참이면 이 값을 취하고 그렇지 않으 면 두 번째 피연산자를 결과값으로 취합니 다 VeryPDF Demo | 호출 뉴-{ ( }--수-r키 표현식 ←키 } … 호출은 함수를 실행합니다. 호출 연산자는 함수 이름 뒤에 이어 지는 한 쌍의 괄호 입니다 팔호 내에 는 함수에 전달하는 인수를 포함할 수 있습니다 함수는 4장에서 자세히 살펴봅니다. 자바섣럽트의 좋은 문볍들 | 35 뉴t뽑훨콘망」 세부지정은 객체의 속성이나 배열의 구성요소를 지정할 때 사용합니다. 세부지정 은 다음 장에서 자세히 살펴봅니다 07 I 리 터 렬 (Literals) 리터럴 숫자리터럴 문자열 리터랄 객체리터럴 배열리터럴 할수 정규표현식 리터럴 VeryPDF Demo 객체 라터럴은 새로운 객체를 생성할 때 편리한 표기법입니다. 속성명은 이름이나 문자열로 지정할 수 있습니다 속성명은 변수가 아니라 리터럴 이름이기 때문에 객 체의 속성명은 반드시 컴파일 시에 알려져야 합니다. 속성의 값은 표현식입니다. 객체 리터럴은 다음 장에서 자세히 살펴봅니다 L R 「ι r 뻐 36 / 배열리터럴 r--ø | 표현식 강키 | ---0-배 열 리터럴은 새로운 배열을 생성할 때 편 리 한 표기법입니다. 배열은 6장에 서 보 다자세하게살펴봅니 다 정규표현석 리터럴 정규표현식 선택 정규 표현식은 7장에서 자세히 살펴봅니다. 08 I 함수(Functions) 할수몸체 J?:f확 I VeryPDF Demo 느I r'\ L혔二」 ν 체 몸 「 함l ( } { ) var 문 H 문장 뉴 0) hanoi(disc - 1 , src , dst , aux) document.write1n ( ’ Move disc ’ + d i sc + ’ from ’ + src + ’ t 。 ’ + dst); hanoi (disc - 1 , aux , src , dst) ; hanoi ( 3 , VeryPDF Demo ’ Src ’, ’ Au x ’ r ’ Dst ’) ; 이 프로그램을 실행하면 3개의 원반에 대한 다음과 같은 해결방법을 볼 수 있습 니다. Move disc 1 from Src to Dst Move disc 2 from Src to Aux Move disc 1 from Dst to Aux Move disc 3 from Src to Dst 總 62 A , 4 ‘ Move d i sc 1 from Aux to Src Move d isc 2 from Aux to Dst Move d isc 1 from Src to Dst Hano i 함수는 필요한 경우 보조 기둥을 사용하며 원반들을 목적지 기둥으로 옮겁 니다. 이 함수는 전체적인 문제 하니를 세부 문제 세 개로 분리합니다. 먼저 위쪽에 있는 원반들을 보조 기퉁으로 옮겨서 바닥에 있는 원반을 드러나게 합니다 이렇게 하면 바닥에 있는 원반을 목적지 기둥으로 옮길 수 있습니다. 마지막으로 보조 기 퉁에 있는 원반을 목적지 기퉁으로 옮겁니다. 보조 기퉁에 있는 남은 원반들의 이 동은 자신을 재귀적으로 호출핸 방식으로 수행됩니다 han o i 함수는 옮겨야 할 원반의 수와 사용할 수 있는 기퉁 세 개를 넘겨 받습니다 han o i는 자신을 재귀적으로 호출할 때 현재 작업하고 있는 원반의 위에 있는 원반 을처리합니다 이러한작업 을 반복하면결국원반이 없는상태에서 함수가호출됩 니다. 이런 경우 아무 것도 하지 않게 되는데 이렇게 함으로써 재귀적 호출이 무한 대 로 일어나지 않게 됩니다. 재귀 함수는 웹 브라우저의 DOM (Document Obj e ct Mode l) 같은 트리 구조를 다루는 데 매우 효과적 입니다 즉 각각의 재귀적 호출이 트리 구조의 항목 하나에 대해 작동하면 효율적으로 트리 구조를 다룰 수 있습니다 // 주어진 노드부 터 HTML 소스 순으로 DOM 트리의 VeryPDF Demo // 모든 노드를 방문하는 wa l k t h e DOM 함수 정 의 // 이 함수는 차례 로각각의 노드를 넘기면서 함수를 호출 // walk the DOM 은각각의 자식 노드틀을처리하기 위해서 // 자신 을호출함 var 씨 alk the DOM functio n wa lk (node , func) func ( node) ; node node .firstChild ; while (node) walk(node , func) ; node node . nextSibling ; 63 // getElementsByAttribute 함수 정의, // 이 함수는 어트리뷰트 이름 ( att) 과 일치하는 값 (value , 이 값은 넘기지 않아도 // 되는 옵션임 )을 인수로 받음 // 이 함수는 노드에서 어트리뷰트 이름을 찾는 함수를 전달하면서 // wa lk the DOM을 호출 // 일치하는 노드는 re s ult s 배열에 저장됨. var getElementsByAttribute var resu l ts functio n (a tt , value) [J ; walk the DOM(document . body , function var actual if = node . nodeType (typeof ac tual (node) 1 && node.ge tAttribute(att); ’ string ’ && (actual === val ue I I typeof value !== ’ string ’ )) { results.push(node) ; }) · I return results ; 몇몇 언어에서는 꼬리 재귀 (t잉1 recursion) 최적화를 제공합니다. 꼬리 재귀 최적 화라는 것은 함수가 자신을 재귀적으로 호출하는 것을 반환하는 방법으로 진행되 는 재귀적 VeryPDF Demo 호출(꼬리 재귀)일 경우 이를 개선하여 속도를 매우 빠르게 향상시키는 반복 실행으로 대체하는 것입니다(다음의 예 참조) 불행하게도 현재 자바스크립 트는 꼬리 재귀 최적화를 제공하지 않습니다. 자신을 매우 깊은 단계까지 호출하는 함수는 반환 스택의 과다 사용으로 제대로 실행되지 않을 수 있습니다. // 꼬리 재귀를 하는 계 숭 (factorial) 함수를 만옮 // 호출자체의 결과를 반환하기 때문에 꼬리 재귀임. // 현재 자바스크립트는 이러한 유형에 대해 최적회를 제공하지 않음. A ι C 椰 64 , funct i on fac t orial(i , a) var fa c torial a a II 1 ; if (i < 2) { retur n a ; 1 , a * i) ; return factorial(i - document . writeln(factorial(4)) ; 09 // 24 I 유효범 위 (Scope) 프로그 래멍 언어에서 유효범위는 변수와 매개변수의 접 근성과 생 존 기간을 제어 합니다 유효범위 는 이름들이 충돌하는 문제를 덜어주고 자동으로 메모리를 관리 하기 때 문에 프로그래머에게는 중요한 개념입니다. var foo function ( 3, b 5; var a var bar var b function 7, c ( 11 ; // 이 시점에 서 a 는 3 , b 는 7 , c 는 11 a += b + c ; VeryPDF Demo / / 이 시 점 에 서 a 는 21 , b는 7 , c 는 11 // 이 시 점 에 서 a 는 3 , b 는 5 , c 는 정의되 지 않음. bar ( ); // 이 시 점 에서 a 는 21 , b 는 5 수 하 n 65 C 언어 유형의 구문을 가진 모든 언어는 블록 유효범위가 있습니다 블록(중괄호 로 묶인 문장들의 집합) 내에서 정의된 모든 변수는 블록의 바깥쪽에서는 접근할 수 없습니다. 블록 내에서 정의된 변수는 블록의 실행이 끝나변 해제됩니다. 이러 한구조는좋은구조입니다 자바스크립트의 블록구문은마치 블록유효범위를지원하는것처럼 보이지만불행히 도블록유효범위가없습니다. 이러한혼란은오류의 원인이 될 여지가충분합니다. 자바스크립트는 함수 유효범위가 있습니다. 즉 함수 내에서 정의된 매개변수와 변 수는 함수 외부에서는 유효하지 않습니다. 반면에 이렇게 내부에서 정의된 변수는 함수 어느 곳에서도 접근할 수 있습니다. 오늘날 대부분의 언어에서는 변수를 가능한 늦게 즉 처음 사용하기 바로 전에 선 언해서 사용할 것을 권하고 있습니다. 하지만 자바스크립트에서는 블록 유효범위 를 지원하지 않기 때문에 이러한 권고가 적용되지 않습니다. 대신에 자바스크립트 에서는 함수에서 사용하는 모든 변수를 함수 첫 부분에서 선언하는 것이 최선의 방법입니다. 10 I 클로저어osure) 유효범위에 관한 좋은 소식 하나는 내부 함수에서 자신을 포함하고 있는 외부 함 매개변수와 VeryPDF수의 Demo 변수들을 접근할 수 있다는 것입 니다 (this와 arguments는 예외 입니다). 이러한 특성은 매우 유용합니다. 내부 함수에서 외부 함수의 변수에 접근할 수 있는 예 는 앞서 재귀적 호출에서 살 펴봤던 ge tE lementsByAttribute 함수에서 볼 수 있습니다. 이 함수에는 results 라 는 변수가 선언돼 있는데 이 results 라는 변수를 walk_the_DOM의 인수로 넘긴 (내부) 함수에서 접근하고 있습니다. 이러한 특성과 관련하여 더 흥미로운 경우는 외부 함수보다 내부 함수가 더 오래 66 빼 유지될 때 입니다. A i T 03. 호출 절 에서 valu e 라는 속성 과 increment라는 메소드를 가진 myObj ect를 살 펴봤습니다 이제 myObject 객체 에 서 허락되지 않은 경우에는 valu e 속성의 값을 변경할 수 없게 하고 싶다고 가정 해 보겠습니다myObj ec t를 객체 리터 럴로 초기화하는 대신에 다음에 나오는 코드처럼 객체 리터럴 을 반환하는 함수를 호출하여 초기화합니다. 이 렇게 하면 increm e nt와 ge tValue를 통해 va lu e 라는 변수에 접근할 수 있지 만 함수 유효범위 때문에 프로 그램의 나머지 부분에서는 접근할 수가 없습니다. v ar myObject var value functio n ( 0; return { increment : function (i nc) value += typeof inc getValue : function ( return value ; } } ( ) ’ number ’ ? inc 1; ) { ,. -- 코드를 잘 살펴보면 myObj ec t에 함수를 할당한 것이 아니라 함수를 호출한 결 과 를 할당하고 있습니다. 맨 마지막 줄에 있는 o 를 주목할 필요가 있습니다. 함수는 메소드 두 개 를 가진 객체 를 반환하며 이 두 메 소드는 계속해서 value라는 변수에 VeryPDF Demo 접근할수있습니다. 03절의 생성자 호출 패턴에서 살펴봤던 Quo 생성자는 s tatus라는 속성과 get_ statu s 라는 메 소드를 가진 객체를 생성합니다. 하지만 status라는 변수를 바로 접 근할 수 있기 때문에 ge tte r 역할을 하는 ge t_status는 별 쓸모가 없어 보입니다. ge t_sta tu s가 쓸모가 있으려면 status 속성이 pnva te 이어야 할 것입 니다. 그러면 이제 그렇 게 되 도록 quo라는 함수를 정의 해 보겠습니다. 67 // qu 。라는 함수를 생성 // 이 함수는 // status 라는 get status 라는 메 소드와 pri vate 속성을 가진 객체를 var quo function (status) return { get status: function return status ; // 반환 ( qu 。의 인 스턴스를 생성 var myQu o quo( " amazed ") document.writ e1n(myQuo . get status( )); quo 함수는 new 키워드 없이 사용하게 설계됐습니다. 그래서 이름을 대문자로 표 기하지 않았습니다. quo를 호출하면 gecstatus 매소드가 있는 객체를 반환합니 다. 이 객체에 대한 참조는 myQuo 에 저장됩니다. gecstatus 메소드는 quo가 이 미 반환된 뒤에도 quo의 status 에 계속해서 접근할 수 있는 권한을 가지게 됩니다. gecstatus는 status 매개변수의 복사본에 접근할 수 있는 권한을 갖는 것이 아니 라 매개변수 그 자체에 대한 접근 권한을 갖습니다. 이러한 것이 가능한 것은 함수 가 자신이 생성된 함수, 즉 자신을 내포하는 함수의 문맥 (context) 에 접근할 수 있 때문입니다. VeryPDF기Demo 이러한 것을 클로저(c!osure) 라고 부릅니다 좀더 유용한 예제를 살펴보겠습니다. // DOM 노드의 색을노란색으로지 정하고흰색 으로 사라지게 하는 // 함수정의. 68 빼 var fade function (node) var 1eve1 1; var step function ( var hex 1eve1 . toString(16); A “7 node . sty1 e.ba c kg roun dC o1or if (leve1 < 15) ( 1eve1 += 1 ; setTimeout(step , 100) ; ’ #FFFF ’ + hex + h ex ; }; s et Timeout(st ep , 100 ); fade (document .body); documen t. body(HTMl (body) 태그에 의해서 만들어지는 노드)를 넘기면서 fade 를 호출합니다 fade는 level의 값을 1 로 설정합니다 그리고 step이라는 함수를 정 의하고, setTimeout을 호출하여 이 함수를 100밀리 초 후에 실행하게 합니다. 여기 까지 수행을 한 후 fade는 종료합니다. 약 10분의 1 초 뒤에 step 합수가 호출됩니다. 이 함수는 fade의 level 값을 16진수 로 변 환한 후 이 를 이 용하여 fade의 매개변수인 node의 배 경색을 변경합니다. 그 리고 나서 fade의 level 값을 살펴본 후 아직 배 경색 이 흰색이 되지 않았으면 level 의 값을 증가시킨 후, setTimeout을 사용하여 같은 작업을 반복하게 합니다. 이제 다시 step 함수가 호출되면 이번에는 fade 내의 변수 level의 값이 2 입니다 fade 함수는 이미 반환됐지만 함수 안의 변수는 이를 필요로 하는 내부 함수가 하 나 이 상 존재하는 경우 계속 유지 됩 니다. VeryPDF Demo 내부 함수가 외부 함수에 있는 변수의 복사본이 아니라 실제 변수에 접 근한다는 것을 이해해야 합니다 그렇지 않으면 다음과 같은 문제가 발생할 수 있습니다. / / 나쁜 예제 / / 잘못된 방법으로 노드 배열에 이벤트 핸들러 함수를 할당하는 함수 정의. // 노드를 클릭하면 해당 노드가 몇 번째 노드인지를 경고창으로 알려주는 것이 / / 함수의 목적 // 하지만항상전체 노드의 수만을보여줌. 69 va r add the hand l ers function (n odes ) var 1 ; for (i 0 ; i < nodes . length ; i += 1) nodes [i] . onclick function (e ) { alert(i) ; // 나쁜 예제 끝‘ add_the_handlers 함수는 각각의 핸들러에 유일한 번호(i)를 전달하도록 고안됐 습니다. 하지만 이러한 의도대 로 동작하지 않는 데 그 이유는 핸들 러 함수가 받는 i가 함수가 만들어 지는 시점의 i가 아니라 그냥 변수 i에 연 결 되기 때문입니다 // 더 나은 예제 ‘ // 올바른 방법으로 노드 배 열 에 이 벤트 핸들러 함수를 할당하는 함수 정의 // 노드를 클릭하면 해당 노드가 몇 번째 노드인지를 경고창으로 알려줌. var add the handlers function (nodes ) var 1 ; for (i 0 ; i < nodes.length ; i += 1) nodes[i ] .oncli c k function (i) return function (e ) alert(i) ; VeryPDF Demo { } (i) ; 이제 onclick에 함수를 할당하는 대신에 새 로 함수를 정의하고 여기에 i를 넘기면 서 곧바로 실행시켰 습니다 실행된 함수는 add_the_handlers 에 정의된 1가 아니라 넘겨받은 i의 값을 이벤트 핸들러 함수에 연 결 하여 반환합니다. 이 반환되 는 이벤 트 핸들 러 함수는 onclick에 할당합니다. 뼈 A 70 ‘, 11 1콜백 함수는 비연속적인 이벤트를 다루는 것을 좀더 쉽게 할 수 있는 방법을 제공합니 다 예를 들어 사용자와 상호작용으로 시작해서 서버로 요청을 하고 마지막으로 요 청 에 대한 웅답을 보여주는 일련의 작업 흐름이 있다고 가정해 보겠습니다. 이러한 작업을 처리하는 가장 고지 식한 방법은 다음과 같을 것입니다. request prepare the request( ); response send request syn ch ronously(request ); dis p lay (response ) ; 이러한 방법으로 작업 을 해결할 때의 문제는 동기화된 요청을 하기 때문에 서버로 부터 웅답이 올 때까지 클라이언트는 꼼짝없이 멈춰서 기다려야 한다는 것입니다. 만약 네트워크나 서버가 느리다면 이 애플리케이션은 웅답성에 있어서 이해할 수 없을 만큼 최악일 것입니다. 이런 작업을 처리하는 좋은 방법은 서버로 요청을 비동기식으로 하고 서버의 웅답 이 왔을 때 호출되 는 콜 백 함수를 제공하는 것입니다. 비동기식 함수는 서버의 웅 답을 기다리지 않고 그 즉시 반환되기 때문에 클라이언트는 멈춤 상태로 빠지지 않습니다. request VeryPDF Demo prepare the reques t( ); send request asynchronously( request , function (respon s e ) display(response ); }) ’ 71 sendJequescasynchronously 함수에 함수를 매개변수로 전달하여 서버로부터 웅답이 왔을 때 호출되게 합니다 5 12 I 모률 함수와 클로저를 사용해서 모률을 만들 수 있습니다. 모률은 내부의 상태나 구현 내용은 숨기고 인터페이스만 제공하는 함수나 객체입니다. 모률을 만들기 위해서 함수를 사용하면 전역변수 사용을 거의 대부분 제거할 수 있기 때문에 결국 자바 스크립트의 최대 약점 중 하나를 보완할 수 있습니다. 예를 들어 String 객체에 deentityify 메소드를 추가한다고 가정해 보겠습니다. 이 메소드는 문자열에서 HIML 엔티티들을 찾고 이들을 그에 상웅하는 문자로 대체 효}는 기능을 합니다. de entityify는 엔티티의 이름과 상웅하는 문자들이 담긴 객체 를 사용해야 합니다. 그런데 이 객체를 어디에 간직해야 할까요? 간단히 생각해서 이 객체를 전역변수로 지정할 수 있습니다. 하지만 전역변수는 사용해서는 안 되는 나쁜 것입니다 또 다른 방법으로 이 객체를 함수 자체 내에 정의할 수도 있습니다. 하지만 이 역시도 함수가 호출될 때마다 매번 객체 리터럴을 객체화 (evaluate) 하 는 실행시간 비용 (runtime cost) 부담이 있습니다. 이상적인 해결 방법은 이 객체 를 클로저에 두고 이 객체에 HTh1L 엔티티를 추가할 수 있는 메소드를 따로 두는 것입니다 VeryPDF Demo String.method( ’ deentityify ’ // 5 , function ( 엔티티 테이블. 엔티티 이 름을 문자에 대웅시킴 억자 주/ 저자의 의도는 콜백 함수라는 함수 호출의 한 형태를 보여주기 위해 간단히 개넘적으로만 설영한 것 같습니다. 그래서 좀더 실질적인 예제를 제시하고 있지 않습니다. 물론 서론에서 저자가 밝혔듯이 슨수한 자바스크립트의 기능에만 초접을 맞추려고 했기 때문에 브라우저에 특화된 비동기식 호출 예제를 제시하지 않은 것 같습니다 콜백 함수의 구체적인 예는 인터넷이나 다른 자바스크립트 책에서 (흔히 Ajax라고 일컬어지는) XmlHtlpRequesl를 시용하여 비동기적으로 서버에 A “ τ 72 뼈 요청하는 예제를 잦tof보면 될니다 var entity quot: lt : ’<’ gt: ’>’ 11 deentityify r 메소드 반환 return function ( 11 여기가 deentityify 메소드 11 문자열의 replace 메소드를 호출하여 &로 시작하고 ; 로 끝나는 11 부분을 찾고 &와 ; 사이의 문자열이 엔티티 테이 블에 있으면 11 해당 문자로 엔티티 를 대체 . 정규 표현식 사용 ( 7 장 참조) . return this . replace ( /& ( [^& ; ] +) ; function var r Ig , (a , b) enti ty[b ] ; return typeof r ’ string ’ ? r a; }; } ( ) ) ·f 코드의 마지막 줄을 잘 보기 바랍니다.0 연산자를 사용하여 방금 막 정의한 함수 를 바로 호활}는 것을 볼 수 있습니다 이 호출로 d ee ntityify 메소드가 되는 함수 를생성해서 반환합니다 VeryPDF Demo docuπ\ent .w riteln ( ’ < ; " ; > ; ’ . deentityify( )); 11 < " > 모률 패턴은 바인딩과 private을 위해 함수의 유효범위와 클로저를 이용합니다. 이 예제에서는 de e nti tyify 메소드만이 엔티티들을 담고 있는 데이터 구조인 entity 객 체에 접근할 수 있습니다. 73 모률의 일반적인 패턴은 private 변수와 함수를 정의하는 함수입니다. 클로저를 통 해 private 변수와 함수에 접근할 수 있는 권한이 있는 함수를 생성하고 이 함수를 반환하거나 접근 가능한 장소에 이를 저장히는 것입니다. 모률 패턴을 사용하면 전역변수 사용을 없앨 수 있습니다. 이 패턴은 정보은닉과 그 외 다른 좋은 설계 방식을 따를 수 있게 하고, 애 플리케이션이나 다른 싱 글톤 Csingleton) 패턴 들을 효과적으로 캡슐화할 수 있게 합니다 모률 패턴은 또한 안전한 객체를 생성하는데도 사용할 수 있습니다. 이제 시리얼 번호를 생성하는 객체를 만든다고 가정해 보겠습니다. var serial maker 11 11 11 11 function 유일한문자열을 생성하는 객체 생성. 유일한 문자열은 접두어와 연속된 숫자 두 부분으로 구성됨 객체에는 접두어와 연속된 숫자를 설정하는 메 소드와 유일한 문자열을 생성히는 gensym 메소드가 있음. var prefix var seq 0; return { set prefix: function (p) prefix String(p) ; set seq : function seq s; g 땐 「」 빠 4 ‘ 1j { ’ = pm m + rf4 l • L serial maker( seqer . set prefix( ’ Q ’ ) ; 74 /‘ ·r ); 쩍 t 잉 var seqer m m un 따 『hμ m m 넉 m 미 야써 q}e π 쩍 VeryPDF Demo (s) seqer . set seq ( 1000) ; var unique seqer . gensym ( ); // unique 는 " Q1000 " 메소드가 this나 앞서 살펴본 that (03절의 함수 호출 패턴 예제 참조)을 사용하지 않 기 때문에 seqer 내부의 변수를 접근할 수 있는 방법은 없습니다. 즉 해당 변수를 다 루도록 정의된 메소드를 제외하고는 prefix나 seq의 값을 얻거나 변경할 수 있는 방 법은 없습니다. seqe r 객체는 변형될 수 있기 때문에 가지고 있는 메소드들은 다른 메소드로 대체될 수 있지만 그렇다고 해서 대체된 메소드들이 숨겨져 있는 prefix와 seq를 접근할 수는 없습니다. seqer 은 단순히 함수들의 집합처 럼 보이지만, 이 함수 들만이 숨겨진 변수들을사용하거 나수정할수 있는권한이 있습니다. seq e r.gensym 을 써 드 파티 함수에 넘기면 유일한 문자열을 생성할 수 있지만 써 드 파티 함수가 pre fix나 seq를 변경 할 수 없습니다. 13 I 연속 호출(Cascade) 일부 메소드는 반환값이 없습니다. 예를 들어 객체의 상태를 변경하거나 설정하는 메소드들은 일반적으로 반환값이 없습니다. 만약 이러한 메소드들이 undefined 대신에 thi s를 반환한다면 연속 호출이 가능합니다 연속 호출을 사용하면 같은 객 체에 대해 문장 하나로 연속되는 많은 메소드를 호출할 수 있습니다. 연속 호출을 가능하게 VeryPDF Demo 하는 Aj ax 라이브러리를 사용하면 다음과 같은 스타일의 프로그래밍이 가능합니다. getElement( ’ myBoxDiv ’ ) . move (350 , 150) . width (1 00) . height (100) . color( ’ red ’ ) . border( ’ 10px outset ’ ) . padding ( ’ 4px ’ ) . appendText ( " P1ease sta nd by " ). 75 。 n( }) ’ mousedown ’ , function (m) this . startDrag(m , this . getNinth(m)); . 。 n( 。 n( ’ mousemove ’ r ’ drag ’ ) . ’ mouseup ’ , ’ stopDrag ’ ) . later (2000 , function ( ) { this . co l or( ’ yellow ’ ) . setHTML( " What hath God wraught? "). slide (400 , 40 , 200 , 200) ; }) . tip ( ’ This box is resizeable ’ ) ; 이 예제에서 getElement 함수는 id가 myBoxDiv~ DOM 엘리먼트에 여러 기능을 추가한 객체를 반환합니다. 이 객체에는 엘 리 먼트를 이동할 수 있는 메소드, 크기 나 스타일을 변경하거나 특정 행동을 추가할 수 있는 메소드들이 포함됩 니 다. 각각 의 메소드는 객체를 반환하기 때문에 각 메 소드 호출 결과를 다음 호출에 사용할 수있습니다. 연속 호출은 매 우 표현적인 인터페이스를 제공할 수 있게 합니다. 연속 호출은 한 번에 많은 작업을 할 수 있는 인터페이스를 만드는데 도움이 됩니다. 14 I 커 링 (Curry) 6 VeryPDF Demo 함수는 값 (value) 이며, 이 함수값을 흥미로운 방법으로 다룰 수 있습니다. 커링은 함수와 인수를 결합하여 새로운 함수를 만들 수 있게 합니다. var addl add . curry(l) ; document . write l n(addl(6)) ; 6 억자 주/ 커링에 익숙하지 않은 분들은 커링이나 Haskell // 7 언어와 커링을 같이 검색하면 원하는 내용을 찾을 수 있습니다‘ 76 빼 그러고 영문이기는 하지만 http://en . wi씨 pedia.org/에씨/Currying에 이주 잘 정리돼 있습니다, A i i addl 은 add의 c lI ny 메소드에 l 을 넘겨서 생성한 함수입니다. addl 함수는 자 신의 인수에 1 을 더합니다. 자바스크립트는 clInγ 메소드가 없지만 다음과 같이 F lInction.prototype 에 이를 추가할 수 있습니다 Funct i on . method ( ’ cu r ry ’, f un c t i on ( var args argume nt s , that this ; retur n fun ction ( return t hat . apply (n u l l , args . co n cat (arguments)); }) ; / / 뭔가 잘못된 점 이 ClI fry 메소드는 커링할 원래 함수와 인수를 유지히는 클로저를 만드는 방식으로 동작합니다. 이 clIn y 메소드는 새로운 함수를 만들어 반환하는데 이렇게 반환되는 함수는 cllny 메 소드를 호출할 때 받은 인수와 자신을 호출할 때 받게 되는 인수를 결합하여 clIrry를 실행한 원래 함수를 호출합니다 curry 메소드는 arguments 배열 두 개 를 연결하기 위해 배열의 concat 메소드를사용합니다. 불행하 게도 앞서 살펴본 것처럼 argllments 배열은 배열이 아닙니다. 그래서 찌 gllments는 concat이라는 메소드가 없습니다. 이 문제를 해 결하기 위해 arguments 배 열 두 개에 배 열의 slice 메 소드를 적용할 것입니다 이렇게 하면 concat 메소드 를 포함하는 진정한 배 열 이 반환됩니다. VeryPDF Demo Function . method ( ’ curry ’ , funct ion ( var slice Array .proto type. s li ce , args sl i ce . a pply(argume nt s ) , that t his ; return function ( return that .apply (null , ar딩s . con,경t(slice. apply ( arguments))) }) ; ·r 77 15 I 메모이제이션 (memoization) 7 함수는 불필요한 작업을 피하기 위해서 이전에 연산한 결과를 저장하고 있는 객체 를 사용할 수 있습니다. 이러한 최적화 기법을 메모이제이션 (memoization) 이라 고 합니다. 자바스크립트의 객체와 배열은 메모이제이션에 매 우 유용합니다. 이제 피보나치 수열을 재귀 함수로 계산하는 경우를 생각해 보겠습니다. 피보나치 수열에서 한 항의 값은 앞선 두 항의 값을 더한 값입니다. 이 수열에서 첫 번째 두 항은 O과 1 입니다. var fibonacci function return n < 2 ? n for // (var i 0; i (n) fibonacci (n - <= 1 0 ; i += 1) document . writeln ( ’ // ’ + l + ’: 1) ’ + fibonacci (n - 2); + fibona cci (i) ) ; 0: 0 // 1: 1 // 2 : 1 / / 3: 2 // 4: 3 // 5: 5 // 6: 8 // 7 : VeryPDF Demo 13 // 8 : 21 // 9 : 34 // 10 : 55 78 역자 주/ 메모이제이션과 관련해서는 빼 7 A “T http://ko.wi kipedia.org/wi ki/Memoization를 침조하세요 이 예제는 잘 동작합니다. 하지만 처리해야 하는 작업이 꽤 많습니다 자그마치 fib onacci 함수를 4 53번이나 호출해야 합니다. 여기에서 11 번은 직접 호출한 것 이고 나머지 442 번은 이미 계산한 값들을 다시 계산하기 위해 호출한 횟수입니다. fib onacci 함수에 메모이제이션을 적용하면 작업량을 현저하게 줄 일 수 있습니다 이전에 작업한 결과는 클로저를 통해 숨겨지는 memo 라는 배열에 저장할 것입니 다 함수가 호출되면 제일 먼저 결과가 저장돼 있는지를 살핍니다. 그 래서 만약 결 과가 있는 경우 연산을 수행하지 않고 바로 결과를 반환합니다. var fibon acci f unc tion var fib func ti o n var result if ( [ 0 , 1] ; va r memo (n) memo [ n] ; (typeo f result ! = = ’ number ’ ) res u l t fib (n - memo[n] 1) + fib (n - { 2); result ; return result ; return } ( fιb ; ) -- 이 함수는 앞서의 함수와 같은 결과를 보이지만 호출은 단지 29번만 발생합니다. 11 번은 직접 호출 한 것이고 나머지 18번은 앞선 메모이제이션 결과를 얻기 위해 VeryPDF Demo 호출한것입니다 이러한 메모이제이션 작업은 메모이제이션 함수를 만들 수 있게 도와주는 함수 를 만들어서 일반화할 수 있습니다. 다음의 예제 코드에 나오는 momoizer 함수 는 결 과를 저장할 배열 ( 매개변 수 memo) 과 메모이제이션을 할 함수( 매개변수 fund a m e ntal) 를 인수로 받습니다. 그런 다음 memo 에 저장되는 데이터를 관리하 고 필요한 경우 fundamental 와 함수가 받게 되 는 인수는 함수를 호출히는 fundamental shell 함수를 반환합니다. shell 함수 함수에 전달합니다. 79 var memoizer function var s h ell function var result (memo , fundamental) (n) memo[n); if (typeof result !== ’ number ’ ) resu l t { fundamental(shell , n); memo [n) re sult ; return result; return she ll; 이제 다음과 같이 매개변수 memo 에 해당하는 배열과 매개변수 fundamental 에 해당하는 메모이제이션할 함수를 memoizer에 전달하여 fibonacci 함수를 정의할 수있습니다. var fibonacci memoizer([O , 1) , func tion (shell , n) re t urn she l l(n - 1) + shell(n - 2 ); }) ·r 이런 식으로 다른 함수를 만들어내는 함수를 고안하면 작업 양을 현저하게 줄일 수 있습니다. 예를 들어 다음과 같이 기본적인 계승 (factorial) 공식만 제공하면 메 모이제이션을 사용하는 factori와이라는 계승 함수를 손쉽게 만들 수 있습니다. VeryPDF Demo var factorial memoizer([l , 1 ) , function (shell , n) return n * shell (n - 1) ; }) 8. r· 역자 주/ 바로 앞에 제시한 코드의 memOlzer에서 shell과 이 예에서의 shel을 구분할 필요가 있습니다 memOlzer에서의 shell은 메모이제이션을 행하는 실제 함수이고, 여기서는 함수를 하나 받아서 시용할 것인데 그 매개변수 이름을 shell로 한 것입니다 물론 여기서 받게 되는 함수는 앞서 제시한 쿄드에 있는 shell이기 때문에 저자는 이러한 돗을 나타내기 위해서 80 뼈 shell이라는 같은 이름을 사용한 것입니다 A “ 1 짧뺏 C.H.A.P.T.E.R 샤소 。기 ... 하나가 여러 대상(object)드로 나누1 는군요. 저 사시경(料視鏡)을 정연으로보니 그저 혼란한 것이… - 윌리엉 셰익스피어, 리처드 2세 *팩:? - - 상속은 대 부분의 프로그래밍 언어에서 중요한 주제입 나다. 자바 같은 클 래 스 기반의 언어에서 상속(또는 확장)은 두 가지 유용한 점을 제 공합 니다 첫 째 로 상속은 코드 재사용의 한 형태입니다. 만약 새 로 만들 클래스가 기 존 에 있는 클 래 스와 매 우 유사하다면, 상속을 통해 단지 다른 점 만을 구현하면 됩니 다. 코드를 재사용하는 패턴 은 소프트웨어 개발 비용을 현저하게 줄일 수 있는 잠 재력이 있기 때 문에 매 우 중요합니다. 클 래스 상속의 또 다른 이점은 상속에 데이 타입 체계의 VeryPDF터Demo 명세가 포함된 다는 것입 니다. 이러한 속성은 프로그 래머들이 명시 적으로 캐 스 팅 작업을 해야 할 필요를 없애줍니다. 만약 상속 시에 캐스팅을 해야 한다면 프로그래머 들의 작업 이 많아지는 것도 많아지 는 것 이지만 데이터 타입 체 계가 안전하게 전달되 는 이 점을 잃 게 됩니다. 데이터 타입 확인이 엄격하지 않은 자바스크립트는 캐스팅 을 절대 하지 않습니다. 객체의 계보는 별 상관이 없습니다. 객체에서 중요한 접은 어떤 일을 하느냐지 어 디서 유래했는지가 아닙니다. 자바스크 립트는 더 풍부한 코드 재사용 패턴 을 제공합니다. 자바스크립트에서 도 81 물론 클래스 패턴처럼 상속을 할 수 있지만 그 보다 더 표현적인 다른 패턴들도 지 원합니다. 자바스크립트에서 가능한 상속 패턴들은 매우 다양합니다. 이번 장에서 는 그 중에서 가장 직관적인 패턴 몇 가지를 살펴볼 것입니다. 물론 훨씬 더 복잡한 방법들이 있지만 언제나 최선의 방법은 단순함을 유지하는 것입니다. 클래스 기반의 언어에서 객체는 클래스의 인스턴스이며 클래스는 다른 클래스로 상속될 수 있습니다. 자바스크립트는 프로토타입 기반 언어인데 이 말은 즉 객체가 다른 객체로 바로 상속된다는 뜻입니다. 01 I 의사 클래스 방식 (Pseudoclassical) 1 자바스크립트는 자신의 프로토타입 본질과 모순되는 점들이 있습니다. 자바스크립 트의 프로토타입 메커니즘은 클래스와 비슷하게 보이는 일부 복잡한 구문들 때문 에 명확히 두드러지질 않습니다. 프로토타입적 본성에 맞게 객체에서 다른 객체로 직접 상속하는 방법을 갖는 대신에 생성자 함수를 통해 객체를 생성하는 것과 같 은 불필요한 간접적인 단계가 있습니다. 함수 객체가 만들어질 때, 함수를 생성하는 Function 생성자는 다음과 같은 코드 를실행합니다. this .p rototype {constructor: this}; VeryPDF Demo 새로운 함수 객체는, 새로운 함수 객체를 값으로 갖는 constructor 라는 속성이 있 는 객체를 prototype 속성에 할당 받습니다. prototype 객체는 상속할 것들이 저 장되는 장소입니다. 자바스크립트는 어떤 함수가 생성자로 사용되기 위해 만들어 졌는지 알 수 있는 방법을 제공하지 않기 때문에 모든 함수는 prototype 객체를 1‘ 역자 주/ 이 책에서 pseudoc떠ss는 의사 클래스라고 번역했습니다 이 단어에 대해 모조 클래스라고 번역하는 경우도 있고 이렇게 번역하는 것이 의미적으로 더 와닿을 수도 있지만 프로그래밍 언어측면에서 의사 쿄드, 의사 난수, 의사 컴퓨터 등 의새擬似)가 많이 사용되고 있기 때문에 의사 클래스라고 번역했습니다 추가로 구글 검색 결괴매|서도 모조 클래스보다 의 뼈 사 클래스가 현저하게 많이 나오고 있습니다- 「、 82 J 갖습니다. prototype 객체 내 에 기본적으로 할당되는 constructor 속성은 유용하 지 않습니다. 중요한 것은 prototype 객체 자체입니다. new 연산자를 사용하여 생성자 호출 패턴으로 함수가 호출되면 함수가 실행되는 방법이 변경됩니다. 만약 new 연산자가 메 소드였다면 , 아마 다음과 같이 구현됐을 것입니다 Function . method ( ’ new ’, function ( // 생성자의 프로토타업을 상속받는 새로운 객체 생성 var that // Object . create (th is . prototype) this 를새로운 객체 에 바인딩하면서 생성자호출 va r other this.app ly (that , argume nts); / / 반환값이 껴체가 아니면, 새로운 객체로 대체 }) . , return (typeof ot h er ’ 。 bject ’ && other) I I that ; _ •••, / 다음과 같이 생성자를 정의하고 pro totype 에 메소드를 추가할 수 있습니다 v ar Mammal fu nction this . name name ; (n ame) VeryPDF Demo Ma mmal . prototype . get name return this . name ; func t i on ( function Mammal . prototype . says return this . saying I I " ; ( 2 역자 주/ 이 코드를 질 이해할 필요가 있습니다‘ 결국 new로 (생성자) 할수를 호출하면 이 함수가 영시적으로 객체를 반환 하지 않는 한 이 함수의 prototype 속성 객체가 프로토타입이 되는 (새로 만든) 객체를 반환합니다 83 그리고 나서 다음과 같이 인스턴스를 생성합니다. var myMammal new Mammal( ’ Herb the Mammal ’ ) ; var name myMammal . get name( ); // ’ Herb the Mammal ’ 이제 생성자 함수를 정의하고 이 함수의 prototype을 M없nrnal 인스턴스로 대체하 는 방식으로 또 다른 의사 클래스 (pseudoclass) 를 만들 수 있습니 다. var Cat function (name) this.name name ; this.say i ng ’ meow ’; // Cat . prototype 을 Mammal 의 새 인스턴스로 대 체 Cat . prototype new Mammal( ); // 새로운 prototype 에 purr 와 get name 메소드 추가 Cat .pro totype .purr function (n) var i , s ' 1; for (i 0 ; i < n ; i += 1) if (s) S S VeryPDF Demo { += ’- ’ ; += ’ r ’ ; return s ; Cat.prototype.get name func ti on ( return this.says( +" + this . name + , + this . says( ); var myCat var says var purr 빼 ‘ F 84 J new Cat( ’ Henrietta ’ ) ; myCat.says( ) ; // ’ meow ’ myCat.purr(5); // ’ r - r - r - r - r ’ var name myCat . get name( ); ’ meow Henrietta meow ’ // 의사 클 래스 패턴은 객체지향처럼 보이게 고안 됐지만 이는 마치 어디 외계에서 온 패턴 같습니다 이렇게 이상한 코드의 일부분을 앞에서 정의했던 method 메소 드와 다음과 같이 inhe rits 메소드를 정의해서 숨길 수 있습니다 Function . method( ’ inherits ’ this . prototype , function new Parent( (Parent) ); return this ; }) ·r inherits 와 m e tho d 메소드는 this를 반환하는데 이 러 한 속성 때문에 연속 호출 스타 일을 사용할 수 있 습니다. 이제 다음과 같이 Cat을 한 문장으로 만들 수 있습 니다 var Cat function (name) this . name name; ’ meow ’; this . saying inherits(Mamma1 ) . method( ’ purr ’ , function var for VeryPDF Demo l , (i if { 0 ; i < n ; i += 1) (s) { S S (n) ” ’ S += ’ - ’ ; += ’ r ’ ; return s ; }) . method( ’ get name ’ , function ( return this. says ( + " + this . n ame + , + this . says( ) ; }) . , 상속 85 객체의 prototype을 사용하는 것을 method와 inherits 라는 메소드를 만들어 숨김 으로써 외계에서 옹 것 같은 부분이 조금 경감됐습니다. 하지만 실제로 훈탱된 부 분이 있을까요? 이제 클래스 같이 동작동F는 생성자 함수를 갖게 됐습니다. 하지만 면변을 살펴보면 전혀 그렇지 않습니다. private은 전혀 없고 모든 속성은 pub 1ic 입니다. 그리고 부모 메소드로의 접근도 전혀 할 수 없습니다. 설상가상으로 생성자 함수를 사용하는데는 심각한 위험이 있습니다 만약 생성자 함수를 호출할 때 new 연산자를 포함하는 것을 잊게 되 면 this는 새로운 객체와 바 인딩되지 않습니다. 불행히도 this는 전역객체와 연결되고 이렇게 됨으로써 새로운 객체에 필요한 기능을 추가하게 되는 것이 아니라 전역변수에 영향을 미치게 됩니 다. 가히 심각한 문제라고 밖에 할 수 없습니다. new를 누락해도 어떠한 컴파일 경 고나실행시간경고가발생하지 않습니다. 이러한 점은 언어에 있어서 심각한 설계 오류입니다. 이러한 문제점을 경감시키기 위한 한가지 방법은 단어 첫 글자를 대문자로 표기하는 표기법(일명 파스칼 표기 법)을 모든 생성자 함수의 이름에 사용하고 그 외 다른 것들은 이 표기법을 사용하 지 않는 것입니다 이러한 방법을 사용함으로써 그나마 new를 빼먹은 것을 보다 쉽게 식별할 수 있습니다. 물론 더 나은 대안은 new를 사용하는 방식을 피하는 것 입니다. 의사 클래스 (pseudoclass) 를 사용하는 방법은 자바스크립트에 익숙하지 않은 프 로그래머들에게 편안함을 제공합니다 하지만 이 방법은 자바스크립트라는 언어가 VeryPDF가진 Demo 진정한 속성을 가리기도 합니다. 클래스에서 영감 받은 표기법은 프로그래머 들에게 불필요하게 복잡하고 단계가 많은 구조를 만들도록 유도할 수 있습니다. 클 래스 계층의 복잡함 대부분은 정적 타입 확인이라는 제약사항으로 인해 발생합니 다. 자바스크립트는 이러한 제약사항으로부터 완전히 자유롭습니다. 클래스 기반 의 언어에서는 클래스 상속이 코드를 재사용할 수 있는 유일한 방법이지만 자바스 크립트는 더 좋은 방법들이 있습니다. 「」 빼 86 ‘ 02 I 객체를 기술하는 객체 (Object Specifiers) 때때로 생성자가 매우 많은 매개변수를 갖는 경우가 있습니다. 이런 경우 일일이 인수의 순서를 외우기가 힘들기 때문에 성가실 수 있습니다 그래서 생성자가 많은 인수를 받는 대신에 객체를 기술하는 하나의 객체를 받도록 정의하면 보다 사용하 기 편리한 형태가 됩니다. 객체를 기술하는 객체는 만들어질 객체의 명세를 포함합 니다. 그래서 다음과 같이 작성하는 대신에 , var myObject 미 aker(f , 1 , m, c , s) 다음과 같이 직성할 수 있습니다 var myObject ma ke r({ , 1ast: 1 , first : f state : s , Clty : c }) . , 이제 인수는 꼭 순서를 맞출 필요가 없으며 생성자가 기본값들을 똑똑하게 설정하 고 있다변 인수를 생략할 수도 있습니다 그리고 이렇게 함으로써 코드의 가독성이 VeryPDF높아집니다, Demo 이러한 방법은 ]SON을 사용하여 작업하는 경우 부가적인 이점을 제공합니다 (JSON은 부록 E를 참조하세요). ]SON 텍스트는 단지 데이터만을 기술할 수 있습 니다. 그런 데 ]SON으로 기술되는 데이터가 객체인 경우 매소드들과 함께 구성됐을 때 , 더 편리한 경우들 이 있습니다. 이를 위해 객체를 기술하는 객체를 받아들이는 생성 지를 사용하면 쉽게 처리할 수 있습니다 즉 간단하게 생성자에 ]SON 객체를 넘기고, 이 생성자가 필요한 기능을 갖춘 객체를 구성하여 반환하는 형식으로 처리 할수있습니다. 상속 87 03 I 프로토타입 방식 순수하게 프로토타입에 기반한 패턴에서는 클래스가 필요 없습니다. 대신에 객체 에만 초점을 맞추면 됩니다. 프로토타업에 의한 상속은 개념적으로 클래스에 의한 상속보다 더 간단합니다. 즉 새로운 객체는 기존 객체의 속성들을 상속받을 수 있 습니다. 이러한 개념이 익숙하지 않을지 모르지만 실제로 이해하기 쉬운 개념업니 다. 일단 먼저 유용한 객체를 만드는 것으로 시작합니다. 그러면 이후부터는 이와 유사한객체들을보다많이 만들수 있습니다. 애플리케이션을중첩된 추상클래스 들로 분해하는 클래스화 과정은 전혀 필요가 없습니다 그러면 이제 유용한 객체를 생성하는 객체 리터렬로 시작해 보겠습니다. var myMammal ’ Herb name ge t name the Mammal function ’ I ( return th i s . name; ), says function ( ) { return this. saying I I "; 일단 위와 같은 객체를 생성하고 나변 3장에서 살펴봤던 Objec t. create 메소드를 사용하여 이 객체의 더 많은 인스턴스를 만들 수 있습니다. 그리고 나서 이렇게 새 VeryPDF Demo 로 만든 언스턴스를 필요에 맞게 맞춤화할 수 있습니다. 즉 인스턴스에 원하는 대 로 메소드나 속성들을 추가할 수 있습니다 3 var myCat myCat.name myCat.saying Object.create(myMammal}; ’ Henrietta ’; ’ meow ’ ; 역자 주/ 프로토타입 방식은 Object.create가 핵심이라고 할 수 있습니다 저자가 권하는 대로 이 메소드를 사용하여 프로 3 토타입 방식으로만 상속을 히는 것도 좋지만 의사 클래스 방식을 이해하고 이 방식을 내부적으로 응용한 소드를 온전히 이해하면 언어를 이해하는데 더욱 도움이 될니다. r L 뼈 88 r 1 J Object. create 메 myCat . purr var l , for (i if function 0 ; i < n ; i += 1) (s) S S (n) ” S { { += '- I ; += ’ r ’ ; return s ; myCat . get name function ( return t his.says + ’ ’ + this . name + ’ ’ + this . says() ; 이러한 방법은 클 래 스에 의한 상속과는 분명히 구별되는 상속 방법입니다. 새 로운 객체 를 맞춤화함으로써 기반이 되는 객체와 차이점을 만들 수 있습니다. 이러한 방법 은 때때 로 기 존의 데이터 구조를 상속받는 데이터 구조에 유용합니다. 다음은 그 예입니다 중괄호로 유효범위 (scope ) 를 지정하는 자바스크립트나 TEX 같은 언어 를 파싱한다고 가정해 보겠습니다. 특정 유효범위 내에 정의된 항목은 바 깥 유효범 위에서 볼 수 없어야 합니다. 어떤 의미에서는 내부의 유효범위가 외부의 유효범위 를 상속받는다고 볼 수 있습니다. 자바스크립트의 객체는 이러한 관계를 나타내 는 데 매우 적합합니다 block이라는 함수는 왼쪽 중괄호를 만나게 되면 호 출됩니다. parse 함수는 유효범위 내에서 심볼들을 검색해서 새로운 심볼이 정의 된 경 우 이 를 scope에 추가합니다. VeryPDF Demo var b10ck function ( // 현 재 scope 를 기억 현재 scope 의 모든 것 을 포함하는 // 새 로운 scope 생 성 var o ldScope scope ; scope Object . create (scope ) // 왼쪽중괄호를지 나 앞으 로 전진 89 advance ( ’{’) ; // 새로운 s co p e 를사용하여 파상 par se (s cope ) ; // 오른쪽 중괄호를 지나 전진, 새로운 scope 를 포기하고 // 이전 scope 복원 advance ( ’ } ’ ) ; scope ol dSco pe ; 04 I 함수를 사용한 방식 지금까지 살펴본 프로토타업에 의한 상속 패턴의 한가지 단점은 private 속성을 가 질 수 없다는 것입니다. 객체의 모든 속성은 public 입니다 private 변수도 private 메소드도 모두 생성할 수 없습니다. 어떤 경우에는 이것이 문제가 안 되지만, 경우 에 따라서는 아주 중요한 문제일 수 있습니다. 특히 골치 아픈 경우는 인식 없는 일 부 프로그래머들이 이상한 방법으로 private을 흉내내는 패턴을 사용하는 경우입 니다 즉 private 이라는 의미로 사용하기 원하는 속성들의 이름을 이상하게 표기하 여 다른 코드에서 이 속성들이 사용되지 않게 하는 경우입니다. 다행히도 앞서 살 펴본 모률 패턴에서 좀더 나은 대안을 찾을 수 있습니다. VeryPDF Demo 먼저 객체를 생성하는 함수를 만드는 것으로 시작할 것입니다. 이 함수는 new 연 산자를 사용하지 않을 것이기 때문에 이름을 소문자로 시작할 것입니다. 이 함수는 다음의 4 단계로 작업을 진행합니다. 1. 새로운 객체를 생성합니다. 객체를 만드는데는 다양한 방법이 있습니다. 객 체 리터럴로 만들 수도 있고, new 연산자를 사용하면서 생성자 함수를 호 출할 수도 있고, 기존의 객체에서 새로운 인스턴스를 만들어주는 Object. create 메소드를 사용할 수도 있으며 , 객체를 반환하는 함수를 호출할 수도 있습니다. ζ 때 90 J 2. 필요한 private 변수와 메소드를 정의합니다. 이것들은 단지 함수 안의 일반 적인 변수입니다. 3. that에 새로운 객체를 할당하고 메소드를 추가합니다. 이때 추가되는 메소 드들은 함수의 매개변수와 2번째 단계에서 정의한 변수들을 접근할 수 있는 권한을갖습니다. 4. 새로운 객체 that을 반환합니다. 다음은 이러한 함수를 위한 의사 코드 (pseudocode) 템플릿입니다(강조를 위해 볼드체를사용했습니다) . var constructor functio n (spec , my) var t hat , 필요한 private 변수들; my my 11 {}; 공유할 변수와 함수를 my에 추가 that 새로운 객체 앞서 정의한 변수들에 접근할 권한이 있는 메소드들을 that에 추가 return that ; VeryPDF spec Demo객체 는 c ons tru c to r가 인스턴스를 만드는데 필요한 모든 정보가 있습니다. spec의 내용들은 private 변수에 복사되거나 다른 함수에 의해서 처리될 수 있습 니다 또한 메소드에서 펼요한 정보를 spec에서 얻을 수도 있습니다(간단한 방법 은 spec을 하나의 값으로 대체하는 것입니다. 객체를 생성하는데 전체 명세를 나 타내 는 spec 객체가 필 요 없는 경우에는 이러한 방법이 유용합니다) . my 객체 는 상속 연 결상에서 생성자와 공유하게 되는 비밀들을 담는 컨테이너입니 다. my 객체 를 사용하는 것은 선택사항입니다.my 객체가 전달되지 않으면 내부에 서 이 객체가 만들어집니다 91 다음은 private 변수와 메소드를 정의하는 것입니다. 방법은 간단합니다. 단지 내부에서 변수와 함수를 정의하면 이것들이 constructor private 변수와 함수가 됩니다. 내부 함수는 spec , my , that과 함께 정의된 모든 (private) 변수를 다 접근 할수있습니다. 다음은 공유할 private 요소들을 my 객체에 추가하는 것입니다. 방법은 다음과 같 이 할당하는것입니다. my.member value; 이제 새로운 객체를 만들고 that에 할당합니다. 새로운 객체는 다양한 방법으로 만 들 수 있습니다. 객체 리터럴로 만들 수도 있고 new 연산자를 사용하는 의사 클래 스 생성자로 만들 수도 있으며 , prototype 객체에 Objec t. create 메소드를 사용할 수도 있습니다. 또한 별도의 함수형 생성자에 습니다(물론 spec과 my spec , my 객체를 넘겨 만들 수도 있 객체는 constructor 에 넘어온 것 그대로 넘길 수 있습니 다) . my 객체는 별도의 생성자와 my에 넣은 것들을 공유하게 합니다. 여기에서 사 용되는 별도의 생성자도 my 객체에 자신만의 비밀을 담아 constructor 에 전달할 수있습니다 4 다음은 객체의 인터페이스를 담당하게 될 메소드들을 that에 추가하는 것입니다 (이 메 소드들은 private 변수들을 접근할 수 있습니다) . 새로운 함수를 that의 구성 VeryPDF Demo 요소로 추가하거나, 더 안전하게 다음과 같이 일단 새로운 함수를 private 메소드 로 정의한 다음에 이 함수를 that에 할당할 수 있습니다. var methodical that .methodical 4 ( methodical; 역자 주/ my 에 대한 이해가 영확하지 않다면 다음에 이어지는 「、 뼈 「」 92 function J 05 클래스 구성을 위한 부속품 절을 보기 바랍니다 이렇게 두 단계를 거처 methodical을 정의하면 좋은 점은 methocidal을 호출하기 원하는 다른 메소드가 tha t. methodical ()로 호출하는 대신 바로 methodical() 로 호출할 수 있다는 것입니다. 또한 that. methodical 이 대체되어 변경이 된다 하더라 도 private 인 methodical은 이러한 변경에 영향을 받지 않기 때문에 , methodical 을 호출하는 메소드는 계속해서 같은 작엽을 수행할 수 있게 됩니다 마지막으로 that을 반환합니다. 이제 앞서 살펴본 mamm외 예제에 이 패턴을 적용해 보겠습니다 여기서는 my가 필요 없기 때문에 my는 없애고 spec 객체만 사용할 것입니다. 다음과 같이 함수를 사용한 패턴을 적용하면 name과 saying은 완전한 private 속 성이 됩니다, 이 속성들은 get_name 과 says 메소드만이 접근할 수 있습니다 var mammal function (spec) var that 二 {} ; that . get name function ( return spec .name; that . says funct i on ( return spec . saying I I "; VeryPDF Demo return that ; var myMammal mammal ( {name : ’ Herb ’ }) ; 의 λ} 클 래 스 패턴에서는 Cat 생성자 함수가 Mammal 생성자가 하는 작업과 같 은 작업을 중복해서 해야만 했습니다 하지만 함수형 패턴에서는 Cat 생성자가 Mammal 생성지를 호출하고 Mammal 생성자가 객체 생성을 위해 필요한 대부분 의 작업을 하기 때문에 이러한 작업이 필요 없습니다. Cat은 다만 자신에게 추가되 는 부분만 신경 쓰면 됩니다. 상속 93 var cat function (spec) spec . saying spec . saying I I ’ meow ’ ; var that mammal(spec); that.purr function (n) var i , s I , for (i 0 ; i < n ; i += 1) if (s) { S += S ’ -’ ; += ’ r ’ ; return s; that.get name function ( return that . says( +" , + that.says( + spec.name + ); return that; var myCat cat({name : ’ Henrietta ’ }) ; 함수형 패턴은 또한 super 메소드를 다룰 수 있는 방법을 제공합니다. 이제 메소드 이름을 받아서 해당 메소드를 실행하는 함수를 반환하는 superior라는 메소드를 만들어 보겠습니다. superior 메소드가 반환하는 함수는 속성이 변경되더라도 원래 함수를호출합니다. VeryPDF Demo Object.method( ’ superlor ’, function (name) var that this , method that[name]; return function ( return method.apply(that , arguments) ; }) ζ 뼈 」 r 94 ,. J 이제 cat과 같으면서 추가적으로 super 메소드를 호출하는 메소드인 get_name을 가진 coolcat을 통해 시험해 보겠습니다. 이를 위해서는 준비가 필요한데, s up e r_ ge Cname 이라는 변수를 선언하고 여기에 superior 메소드를 호출한 결과를 할당 하는것입니다. var coolcat va r that func t ion (spec) cat (spec ) , super get name that . superi o r( ’ get name ’ ) ; that.get name function (n) return ’ l i ke ’ + super get n a me( ) + ’ baby ’ ; re tu rn that ; var myCoolCat coolcat ({name : ’ Bix ’ }) ; var name myCoo l Cat . get name( ); // ’ li ke meow Bix meow bab y ’ 함수형 패턴은 유연성이 매우 좋습니다. 이 패턴은 의사 클 래스 패턴보다 작업량이 적고 캡슐화와 정보은닉 그 리고 super 메소드에 접근할 수 있는 방법까지 제공합 니다 객체의 상태 모두가 private 이면 객체는 방탄이 됩니다. 객체의 속성은 대체되거나 삭제될 수 있지만 껴체의 무결성은 전혀 영향을 받지 않습니다. 함수형 스타일로 VeryPDF Demo 객체를 만들고 객체의 모든 메소드가 this나 (this를 할당받는) that을 사용하지 않 는다면 이 객체 는 영구적으로 변치 않습니다. 이러한 객체는 단순히 다양한 기능을 하는 함수들을 모아 놓은 집합 역할을 합니다 이러한 객체는 절 대 타협하지 않습니다. 이러한 객체는 주어진 메소드 외에는 내부 상태를 접근할 수 없기 때문에 악의적인 공격자들로부터 안전합니다. 샘 % 05 I 클래스 구성을 위한 부속품 제품을 만들 때 부속품들을 가져다 조립을 송}듯이 객체를 구성할 때 도 같은 방법 으로 할 수 있습니다. 간단하게 이벤트 처리 기능을 객체에 추가하는 함수의 예 를 통해 이를 살펴보겠습니다 이 함수는 on , fire 메 소드와 이벤트 목록을 관리하는 pnvate 속성의 regis띠를 객체에 추가합니다. var eventuality var regis try that.fire function {} ; function (that) (event) 11 객체에서 이벤트에 상웅하는 처리기를 실행사킴 11 매개변수 event 는 이벤트 이름을 포함하는 문자열이거나 11 이벤트 이름을 갖고 있는 type 속성을 가진 객체일 수 있음11 on 메 소드에 의해 등록되는 이벤트 이름과 같은 처리 함수가 호출됨, var array , func , handler , l , type 11 11 해당 이벤트에 상웅하는 처리 함수 목록 배 열이 있으면 루프를 돌면서 이 배열에 둥록돼 있는 모든 처리 함수를 실행시킴 VeryPDF Demo 11 11 11 11 typeof event ’ string ’ ? event event.typ e ; if (regi st ry.hasOwnProperty(type)) { array reg istry[type]; for (i 0 ; i < array . length ; i += 1) handler array[i] ; 처리 함수 배열에 속하는 항목 하나는 처리 함수인 meth od 와 매개변수인 parameter s 라는 배열로 구성됨 (parameter s 는 옵션) . method 가 함수 자체가 아니라 이 름 이면 t his 에 서 해당 함수를 찾읍 func 때 r k 」 96 { handler.method ; if (typeof func ’ string ’ ) func this[func] ; // 처리 함수 호출 ( parameters 가 있으면 이 를 넘김 / / 만약 없으면 event 객체를 넘김 func . apply(this , handler . parameters 11 [event] ); return this ; that . on function (type , method , parameters) / / 이벤트 동록 handler 항목을 만들고 해당 이벤트 타입의 배 열 에 추가‘ / / 만약 기 존에 배 열 이 없다면 해당 이벤트 타입에 대해 새 로운 배열 생성 var handler method : method , parameters : parameters if ( registry . hasOwnProperty(typ e )) registry[type ] . push(handler); } else ( registry[type] [handler] ; return this ; VeryPDF Demo return that ; 이제 원하는 객체에 특정 이벤트 처리를 위해 eve ntuality를 호출할 수 있습니 다 또한 앞서 살펴본 con s truc to r 함수에서 that을 반환하기 전에 다음과 같이 eventuality를 호출할 수도 있습니다. eventuality(that) ; 이러한 방법으로 constructor는 객체에 필요한 기능을 마치 부품을 가져다 조립 하듯 추가할 수 있습니다(즉, 이 예처럼 객체에 이벤트 관련 기능이 필요한 경우 eventuality라는 부속을 사용하여 해당 기능을 추가할 수 있습니다) . 자바스크립트 의 엄격하지 않은 데이터 타입 체크는 이런 부분에서 큰 이점을 줍니다. 왜냐하면 클래스의 상속 계통에서 일일이 데이터 타입 체계를 신경쓸 필요가 없기 때문입니 다. 대신에 각각이 가진 내용과 기능들에만 초점을 맞추면 됩니다. 만약 eventu ality에서 객체의 private 부분들을 접근하기 원한다면 my를 넘기면 됩니다 5 5 역자 주/ 예를 든 eventuality의 기능은 다음의 간단한 예제를 실행해보면 쉽게 이해할 수 있습니다. < ’ DOCTYPE html PUBLIC "- //W3C//DTD XHTML 1.0 Transitional//EN " " http : //www . w 3 . org/T R /xhtrnl1/DTD/xhtml1 - transitι 。 na l. dtd " > eventuality 예제 </ti t1 e> </head> VeryPDF Demo <body> 사각형을 클릭하세요<br> <div i d= " divTest " sty le= " 싸 idth : 100px ; height: 100px; cursor :pointer ;" onclick= " this.fire(event) " ></div> <script type= " te xt/j avascri p t " > bord er : solid lpx black ; <’ -var eventua l ity fu nction (that) 함수 내용은 위의 내용 참조 「、」 98 빼 var oDiv eventuality(docurnent . getElernentById( ’ divTest ’) ) ; 。 Div . on ( ’ click ’ • function() {ale rt( ’ test ’ ) )) ; //--> </script> </body> </html > 戀혔앓 C. H . A. P. T. E . R/ I'i"f. 배옐 너 는 내가 몰아내겠다 양 가죽(sheep’s array)을 쓴 늑대야. - 윌리얻 셰익스피어, 헨리 6서l 저'/1부 배열은 해당 항목의 오프셋을 계산할 수 있는 정수를 통해 각 항 *택? - - 목들을 접 근할 수 있는 연속적인 메모리 할당입니다. 보통 배열은 매우 빠른 데이터 구조입니다 하지만 불행하게도 자바스크립트에는 이런 류의 배 열은없습니다 대신에 자바스크립트는 배 열 같은 특성을 지닌 객체를 제공합니다. 자바스크립트 는 배 열 첨자를 문자열로 변환하여 속성을 만듭니다. 이는 실제 배열보다 심각하게 VeryPDF느리지만, Demo 사용하는 데 는 더 편리할 수 있습니다. 속성들을 읽거나 갱신하는 작업은 정수형 이 름을 가진 속성 에 좀 특별한 트릭이 있다는 것을 제외하고는 일반 객체 와 똑같습니다 배 열 에 는 자신만의 리터럴 형식이 있습니다, 또한 배열에는 8장에 기술돼 있는것처럼 매우유용한내장메소드들 이 있습니다. 99 01 I 배열 리터렬 배열 리터렬은 새로운 배열을 만드는데 매우 편리한 표기법으로 값이 없거나 하나 이상의 값을 쉽표로 구분하여 대괄호로 묶은 것입니다 배열 리터 럴은 표현식이 위 치할 수 있는 곳이라면 어디에라도 위치할 수 있습니다. 배열의 첫 번째 값은 속성 ‘0’으로 읽을 수 있습니다. 두 번째는 ‘ 1’, 세 번째는 ‘ 2 ’ 이런 식으로 배열 요소들을 읽을수있습니다. var empty []; var n u mbers ’ z er 。 ’ r ’ 。 ne ’ ’ five ’ ’ six ’ r r f ’ tw 。 ’ , ’ three ’ ’ four ’ , ’ seven ’ r ’ eight ’, ’ nine ’ I empty [l ] 11 undefined numbers[l] 11 empty .1 engt h 11 0 11 10 numbers . length ’ 。 ne ’ 다음은 유사한 결과를 보이는 객체 리터럴입니다. var numbers object VeryPDF Demo ' 0 ’ : ‘’ ’, ’ 3 ’ : ’ thre e ’ , '6' ’ six ’ ’ 9 ’ : ’ nlne ’ ze r 。 y ’l ’ ' one ’ ’ 4 ’ : ’ four ’ r ’ 7 ’ : ’ seven ’ y f ’ 2 ’ : ’ tw 。 ’ , ’ 5 ’: ’ five ’, ’ 8 ’ : ’ eight ’ f numb e rs와 number_obj ect 모두 10개의 속성을 가졌고 각 속성은 모두 같은 이 름과 같은 값이 있습니다. 하지만 두 객체에 근본적인 차이점이 있는데, numbers 는 Array. proto typ e을 상속했고, number_o bj e ct는 Obj ect. prototype을 상속했 빼 r 100 o 디는 점입니다. 그래서 number s 만이 많은 수의 유용한 메 소드를 상속하게 됩니 다. 또한 number s는 numbe rs_o bj ec t가 가지지 못한 length라는 신비한 속성이 있습니다 대부분의 언어에서 배 열 의 구성요소들은 모두 같은 데이터 타입이어야 합니다 하 지 만 자바스크립 트에 서는 배 열 하나에 어떤 데이터 타입의 조합이라도 다 포함될 수있습니다. v ar misc 98 . 6 , tr u e , fal s e , n u l l ’ strin g ’ [ ’ ne ste d ’ ’ arra y ’ ], r , {object : t ru e} un d e fi n ed , , Na N, Infinity misc .l ength // 1 0 02 I length 속성 모든 배 열은 le n gth 속성이 있습니다. 여타 다른 언어 들과는 달리 자바스크립 트에 서 배 열 의 길 이 는 상계 ( uppe r b o und ) 기반이 아닙니다. 만약 현재 length보다 더 큰 첨자로 항목을 추가하면 l ength는 새로운 항목을 추가할 수 있 게 늘어납니다. 어떠 한 배 열 경 계 오류도 발생 하지 않습니다. VeryPDFle Demo n g th 속성 은 배 열 의 가장 큰 정 수 속성 이름보다 하나 더 큰 값입니다. 그렇기 때 문에 l e n g th 의 값이 배 열 에 있는 속성의 수와 반드시 일치하는 것은 아닙니다. v ar myArray [J ; myArray . length myArray [1000000 J myArray . length // // 0 true ; // 1000001 myArray 는 단지 하나의 속성만가짐. 101 첨지를 둘러싸는 [] 연산자는 안쪽의 표현식이 toString 메소드를 가진 경우 이 를 사용하여 표현식을 문자열로 변환합니다 이 렇게 변환된 문자열이 속성 이름으 로 사용됩니다. 만약 문자열이 배열의 현재 length 값보다 크거나 같은 양수이면서 4 , 294 , 967 , 295 보다 작은 경우 배열의 length 속성의 값은 새로운 첨자에 1 이 더해 진값으로할당됩니다. length의 값은 명시적으로 설정할 수 있습니다.length 값을 크게 설정해도 배열 을 위해 더 많은 공간이 할당되지는 않습니다. 하지만 length 값을 현재 보다 작 게 셜정했을 경우 설정한 값보다 크거나 같은 첨자에 해당하는 속성은 모두 삭제 됩니다. numbers . length 11 numbers is 3; ’ zer 。 ’ r 새로운 항목을 배열의 현재 ’ 。 ne ’ I ’ tw 。 ’ ] length 값으로 추가하면 배열의 끝에다 추가할 수 있습 니다 numbers[numbers.length] 11 numbers is ’ zer 。 ’ r ’ sh i ’; ’ 。 ne ’ I ’ tw 。 ’ r ’ s hi ’ ] 배열의 마지막에 새로운 항목을 추가하는 것은 때때로 VeryPDF Demo push 메소드를 사용하는 것 이더욱편리합니다. numbers . push( ’ g 。 ’ ) ; 11 numb e rs is 때 102 t U [’ z er 。 ’, ’ 。 ne ’, ’ tw 。 ’, ’ shi ’ r ’ g。 ’ ] 03 I 삭제 자바스크립트의 배열은 실제 객체이기 때문에 배열의 요소를 삭제하는데 delete 연산자를 사용할 수 있습니다. d e lete numbers[ 2 l ; // numbers 는 [ ’ zer 。 ’ r ’ 。 ne ’ undefine d , ’ s hi ’ , ’ 9 。 ’ ] 불행히도 이런 식으로 배열의 요소를 삭제하면 그 위치에 구멍이 생기게 됩니다. 즉삭제한요소의 오른쪽에 있는것들은 계속해서 자신의 원래 이름을유지합니다 하지만 배열의 한 요소를 삭제했을 때 보통 원하는 것은 삭제한 요소 오른쪽 요소 들의 이 름 이 수치적으로 하나씩 줄어들게 변하는 것입니다 다행히 도 자바스크 립 트 배열에는 splice 라는 머1 소드가 있습니다. 이 메소드는 배열 을 수술할 수 있는 능력 이 있는데, 즉 배열 요소의 일부를 삭제하고 이를 나머지 요 소들로 대체 할 수 있습니다 이 메소드의 첫 번째 인수는 배열의 시작점이고 두 번 째 인수는 삭제 할 요소의 수입니다. 이 외의 추가적인 인수들은 배열의 삭제한 지 점에 추가되 는 요소들 입니다. numbers . splice (2 , 1) ; // numbers 는 [ ’ zer 。 ’, ’ 。 n e ’, ’ shi ’, ’ 9。 ’ ] VeryPDF Demo 값이 ‘ shi ’ 인 속성의 이 름은 3에서 2로 변경됩니다. 삭제된 속성 뒤에 있는 모든 속 성은 삭제된 후에 새 로운 이 름으로 다시 삽입됩니다. 이러한 과정을 거치기 때문에 배열이 아주 큰 경우에 는 빠르게 동작하지 않을 수 있습나다. 10 3 04 I 열거 계속 언급되지만 자바스크립트의 배열은 실제 객체이기 때문에 for in 문으로 배열 의 모든 속성을 열거할 수 있습니다. 하지만 for in 문이 배열을 열거하는데 그다지 적합한 편은 아닙니다. 왜냐하면 대부분의 배열을 열거하는 작업에서는 배열의 첨 자 순으로 열거되는 것을 당연하게 생각하는데 반해 fo r in 문은 속성들의 순서를 보장하지 않습니다. 또한 fo r in 문을 사용하면 프로토타입 체인 (prototype chain) 에 있는 예상치 못한 속성도 열거될 수 있습니다. 다행히도 일반적인 for 문을 사용하여 이러한 문제를 피할 수 있습니다. 다음의 예 처럼 배열의 length 속성을 반복 횟수의 조건으로 하여 for 문을 사용하면 됩니다 var for (i 0 ; i < myArray . length ; i += 1 ) { document . writeln(myArray[i]) ; ~; 05 I 객체와 배열의 혼동 자바스크립트 프로그램에서 흔한 오류 중 하냐는 배열이 필요할 때 객체를 사용한 다거나 객체가 필요할 때 배열을 사용하는 경우입니다. 규칙은 간단합니다. 속성 VeryPDF이름이 Demo작은크기의 연속된 정수이면 배열을사용하고그렇지 않으면 객체를사용 하는것입니다. 자바스크립트 자체도 배열과 객체의 차이점을 혼동하고 있다고 볼 수 있습니다. 왜 냐하면 typeof 연산자로 배열의 타입을 확인해보면 ‘ array’ 가 아니라 ‘ object’라고 알려주기 때문입니다. 자바스크립트에는 배열과 객체를 구분하는 마땅한 메커니즘이 없습니다. 이러한 결점을 보완하기 위해 다음과 같은 ls_array 함수를 만들어 사용할 수 있습니다. 뼈 104 r o γar is array function (value) return value && ’ 。 bject ’ typeof value value . constructor && Array ; 이 함수는 한가지 문제가 있는데 다른 창 (window) 이나 프레임에서 생성한 배 열 은 구분하지 못한다는 것입니다. 이러한 문제점을 고치려면 다음과 같이 좀더 작업 을해야합니다. var is array function (value ) return value && typeof value ’ 。 bjec t ’ && ’ number ’ && typeof γalue.splice ’ funct ion ’ && (value . propert y IsEnumerable ( ’ l ength ’ )) ; typeof value . length 먼저 v외ue가 참인지를 확인 합니다. 이렇게 함으로써 null이나 여타 다른 거짓값을 배제 할 수 있습니다 두 번째로 typeof value가 object 인지 확인합니다 v띠ue가 객체나 배 열 또는 (조금 이상하지만) null인 경우에 참이 됩니다. 세 번째로 value에 숫자값을 가진 le n g th 속성 이 있는지를 확인합니다. 이 부분은 배열인 경우에 항상 참이며 객 체인 경우에 는 보통 거짓입니다. 네 번째로 value가 splice 메소드를 가졌 VeryPDF Demo 는지 를 확인합니다. 이 부분은 배열인 경우에만 참이 됩니다 마지막으로 length 속 성이 열거 가능한지를 확인 합니다. 즉 fα m문으로 열거 가능한지를 확인하는 것 입니다. 배 열 인 경우 length는 열 거할 수 없습니다 이러한 방법이 필자가 찾아낸 가장 신뢰할 만한 방법 입 니다. 이 방법의 문제점이라면 절차가 좀 복잡하다는 것입 니다 이러 한 확인 방법을 사용하면 넘어온 값이 단일 값인지 배열인지를 구분하여 그에 맞는 작업을 하는 함수를 만들 수 있습니다. 배열 10 5 배열의 메소드 06 I 자바스크립트는 배열에 동작하는 메소드들을 제공합니다. 이 메소드들은 Ar ray. prototype 에 저장돼 있는 함수들입니다.3장에서 Objec t. prototype 에 원하는 것 들을 추가하는 것을 살펴본 것처럼, Array.prototype 에도 원하는 메소드를 추가할 수있습니다. 예를 들어 배열을 대상으로 연산을 할 수 있는 메소드를 추가하고 싶다고 가정해 보겠습니다. Array.method( ’ reduce ’, function var l; for (f , va1ue) 0; i < this.1ength; i += 1) (i f(this [ i ] , va1ue); va1ue return va1ue; }) ,. Array.prototype 에 함수를 추가하면 모든 배열이 추가한 메소드를 상속받게 됩니 다. 이제 함수와 시작값을 취핸 reduce 라는 메소드를 정의했습니다. 배열의 각 요소들은 reduce 에 넘겨진 함수에 v외ue와 같이 넘겨지고 계산된 값이 다시 value 에 저장됩니다. 모든 작업을 마쳤을 때 value를 반환합니다. 만약 두 수를 더하는 함수를 넘겼다면 VeryPDF Demo reduce 호출의 결과는 배열 요소들 전체의 합이 되고, 두 수를 곱 하는 함수를 넘겼다변 전체의 곱이 됩니다. // 숫자들이 요소인 배열 생성 [ 4 , 8 , 15 , 16 , 23 , 42]; var data // 간단한함수두개를정의 뽑 빼 106 r b 함 var add ” 수 T 고며 i ( 름」 두 μ // 하나는 두 수를 더하는 함수이고 다른 하나는 1 function (a , b) return a + b; var mult function (a , b) return a * b; // add 함수를 넘기면서 data 의 reduce data . reduce(add , 0) ; var sum // multiply 함수를 넘기면서 var product reduce 메소드 호출 // 합은 108 메소드를 다시 호출 data.reduce(mult , 1); // 곱은 74188 80 배열은 실제 객체이기 때문에 다음과 같이 개별 배열에 직접적으로 메소드를 추가 할수있습니다. // data 배열에 total 메소 드 추가. data . total func t io n ( return this .reduce(add , 0) ; total data . total( ); // t ota l 는 108 VeryPDF Demo 문자열 ‘ to tal ’은 정수가 아니기 때문에 , total 속성을 추가한다고 해도 length의 값 은 변하지 않습니다. 배열은 속성들의 이름이 정수일 때 가장 유용하지만 배열은 객체이 고 객체는 어떠한 문자열도 속성 이름으로 허용합니다. 3장에 나오는 Objec t. create 메소드는 배열이 아니라 객체를 반환하기 때문에 배 열에 사용하는 것은 별로 유용하지 않습니다. Object . create로 배열을 받아 만들 어진 객체는 배열의 값과 메소드를 상속받기는 하지만 배열의 특수 속성인 length 는갖지 못합니다. 10 7 배열의 크기와 차원 07 I 자바스크립트의 배열은 보통 초기화되지 않습니다. 만약 새로운 배열을 []로 만 들게 되면 배열은 비어있게 됩니다. 그리고 존재하지 않는 요소를 접근하게 되면 undefmed 값을 얻게 됩니다. 이러한 사실을 알고 있거나 또는 배열 요소를 참조하 기 전에 모든 배열 요소의 값을 설정한다면 배열을 사용핸데 아무런 문제가 없 습니다. 하지만 만약에 배열의 모든 요소가 0과 같이 알 수 있는 값으로 시작한다 고 가정히는 알고리즘을 구현하는 경우라면 이에 문제가 없게 배열을 준비시켜야 합니다. 이를 위해 자바스크립트는 Array.clim 같은 메소드를 제공했어야 합니다. 하지만 현실은 그렇지 못하며 다음과 같은 메소드를 정의함으로써 이러한 결점을 고칠수있습니다. Array.dim function (dimension , initial) var a [] , i; for (i 0 ; i < dimension ; i += 1) a[i] initial; return a ; 10 개의 11 0 을 갖는 배열 생성. Array . dim (10 , 0); var myArray VeryPDF Demo 자바스크립트에는 다차원 배열이 없지만 대부분 C 유형의 언어처럼 다음과 같이 배열의 배열을 사용할 수 있습니다. var matrix [0 , 1 , 2] 4, 5 ], [6 , 7, 8] matrix[2] [1] L π r 뻐 108 , [3 , r R O 11 7 2차원 배열이나 배열들의 배열을 만들기 위해서는 다음과 같이 직접 배열을 만들 어야합니다. for 0 (i < n; i i my array[i] += 1 [] ; // 주의 Array. dim(n. [ ] )는 여기에서 동작하지 않음 // 각각의 요소들 이 같은 배열의 참조를 갖게 됨 이 코드는 각 배열 들을 초기화하지 못합니다. my_array의 요소들인 각 배열을 초 기화하려면 일일이 명시적으로 설정해야 합니다 이런 경우를 위해 자바스크 립 트 가 행렬을 위한 메소드를 지원하면 좋겠지만 역시 그렇지 못합니다. 다시 한번 이 러한 결점을 다음과 같은 코드로 보완할 수 있습니다. Array . matrix var a f or function , i , j , ma t (i a = for 0; i < m; i += 1) [ ]; (j 0; a[j] mat[i] VeryPDF Demo (m, n , initial ) []; j < n; += 1) initial ; a; return mat; // 0 으로 채워진 4 * 4 행럴생성 var myMatrix Array.matrix(4 , 4 , 0) ; document . wri teln (myMa tri x [3 ] [3] ) ; // 0 // 행과 열 이 같은 수의 행렬을 만드는 메소 드 10 9 Array.identity function (n) var i , mat Array . matrix(n , n , 0) for (i 0; i < n; i += 1) ma t [ i] [i] 1; return mat; myMatrix Array.identity(4); document. wri teln (myMatrix [3] [3] ) ; VeryPDF Demo 願 110 t U 11 1 蠻 ν C. H . A . P. T. E . R,,:- 'f i 쟁유표현식 그러 나 그 반대의 경우는 천복을 가져오며, 명화의 모범(pa ttern) 인 것 입니다 국왕 헨리 폐하에게 어울리는(match) 배우자는 - ~w:y ‘…/、_.ι . 윌리엉 셰익스피어, 헨리 6서l 제l부 자바스크립트의 많은 부분은 다른 언어들에서 차용한 것입니다. 구문은 자바, 함수는 Scheme , 프로토타입에 의한 상속은 Self'에 서 비 롯된 것입니다 그리고 자바스크립트의 정규 표현식은 Perl에서 가져온 것입 니다 정규 표현식은 간단한 언 어 구문의 특화된 형태입니다. 정규 표현식은 문자열에서 특정 내 용을 찾거나 대체 또는 발혜하는데 사용합니다 정규 표현식을 사용하는 메 VeryPDF소드는 Demoregexp.exec , regexp.test, string.match , string.replace , string.search , string.split 둥 이 있습니다. 이러한 메소드들에 대해서 는 8장에서 셜명합니다. 자 바스크립트에서 정규 표현식은 보통 같은 문자열에 대해 반복해서 연산을 수행할 때 주목할 만한 성능상의 이 점 이 있습니다. 정규 표현식은 정규 언어에 대한 수학적 연구에서 비 롯된 것입 니다. 은 Stephen Kl e e n e 의 이 론을 type-3 Ken Thompson 언어에 적용하여, 텍 스트 에디터 같은 툴이 나 프로그 래밍 언어에서 특정 패턴을 찾을 수 있 게 실질적인 패턴 매칭 기능을 추 가했습니다. 시「 행」 저。 규 III 자바스크립트에서 정규 표현식 구문은 약간의 재해석과 Perl의 확장 구문을 채택 한 것을 제외하고는 벨 연구소1 에서 비롯된 원래의 체계를 거의 그대로 따르고 있 습니다. 정규 표현식에서는 특정 위치의 문자가 연산자로 해석되고 또 조금은 다른 위치에 있는 문자를 리터럴로 간주하기 때문에 이를 작성하는 것은 매우 복잡할 수 있습니다 그런데 작성의 어려움보다 더 안 좋은 것은 이러한 어려움이 정규 표 현식을 읽기 어렵게 만들고 수정하기 위험하게 만든다는 것입니다. 정규 표현식을 바르게 읽기 위해서는 복잡한 정규 표현식 체계 전체를 온전히 이해해야 합니다. 필자는 이러한 어려움을 조금이나마 쉽게 하기 위해서 규칙들을 조금 단순화시켰 습니다. 이 장에서 설명하는 방식으로 하면 정규 표현식이 간결한 편은 아닐지 몰 라도, 바르게 사용하는 데는 생각보다 쉬울 수 있습니다. 또한 이렇게 하면 유지보 수나 디버깅의 어려움을 조금이라도 경감할 수 있습니다. 오늘날의 정규 표현식은 엄격하게 정규적이지는 않지만 매우 유용합니다 정규 표 현식은 매우 간결해지는 경향이 있습니다. 그래서 심지어는 암호화된 것처럼 보이 는 것도 있습니다. 간단한 형태에서는 사용이 쉽지만, 곧 하나 둘 추가되다 보면 급 격히 복잡해집니다. 자바스크립트의 정규 표현식은 주석이나 공백을 허용하지 않 기 때문에 다소 읽기가 어렵습니다. 즉 정규 표현식의 모든 부분은 빈틈 없이 하나 로 연결돼 있기 때문에 해석하기가 쉽지 않습니다. 이러한 부분은 정규 표현식이 탐색이나 검증을 위해 보안 애플리케이션에서 사용될 때 특히 염려되는 부분입니 다. 정규 표현식을 제대로 읽고 해석할 수 없다변 어떻게 원하는대로 동작한다고 확신할 수 있을까요? 하지만 이러한 명백한 단점에도 불구하고 정규 표현식은 널 VeryPDF Demo 리사용되고있습니다. 역자 주/ Ken Tompsonül 빼 1 7 112 t 일하던 콧 벨 연구소는 킴뮤터 역사에 있어서 많은 역할을 합니다. 01 I 예제 다음은 URL에 일치하는 정규 표현식 예제입니다. 이 책의 폭은 무한대로 넓지 않 기 때 문에 예제를 두 줄로 나눴습니다. 하지만 편의상 둘로 나눈 것뿐이며, 실 제 자바스크립트 프로그램 에서 정규 표현식은 한 줄 이어야만 합니다. 공백문자 (Whitespace) 는 사용할 수 없습니다. var parse url /^ (? : ([A- Za - z]+) : )?(\/{0 , 3}) ([0 - 9 . \ A- Za - z] +) (? : : ( \ d+) )? (? : \ /( [ ^?#]*))?(? : \ ? ( [^#] *) ) ? (? : # ( . *) ) ?$/ ; var url .. http://www . ora . com:80/goodp arts?q#fragment .. ; parse_url의 exec 메소드를 호출해 보겠습니다. 이 메소드는 넘겨받은 URL 문자 열에서 일치하는 부분을 찾게 되는 경우 이 부분들을 추출하여 배열에 담아 반환 합니다 '' http : //ww 씨 . ora . com :8 0/goodparts?q#fragment "; var url γar result var names ’ path ’ , var blanks VeryPDF Demo l 、l ar fo r parse url . exec(u rl); ’ url ’ , ’ scheme ’ ’ slash ’ , ’ host ’ ’ query ’ , ’ hash ’ ] ; I ’ I ’ port ’ I ’ r- ; (i 0 ; i < names . length ; i += 1 ) document .w riteln (n ames [i] + ’ : ’ + blanks . substring (names[i] .l ength ) , result[i]) ; 실행 결과는 다음과 같습니다 url : http : //www . ora . com : 80/goodparts?q#fragment scheme : http 시「 핵 저。 규 II3 slash : // host : www.ora . com port : 80 path : goodparts query: q hash : fragment 2장에서는 자바스크립트 언어를 기술하기 위해서 철도 다이어그램을 사용했습니 다. 이 다이어그램은 정 규 표현식으로 정의된 내용을 기술하는데도 사용할 수 있 습니다. 철도다이어그랩을사용하여 표현하면 정규표현식이 하는 일을보다쉽게 이해할 수 있습니다. 다음은 prase_url에 대한 철도 다이어그램입니다. 호스트 문자나숫자, 마침표(.), - 경로 ?와#을제외한 VeryPDF Demo 모든문자 쿼리스트링 #을제외한 모든문자 앵커 줄 마칩을 제외한모든문자 뼈 r 」 114 ? / 정규 표현식은 함수처럼 작은 부분으로 나닐 수 없기 때문에 parse_url을 나타내 는 트랙은 여러 개가 아니라 길게 이어진 하나입니다 이제 parse_url의 각 부분들이 어떻게 동작하는지 분해해 보겠습니다 A 문지는 문자열의 시작을 나타냄니다. 이 문자는 exec 메소드가 URL 같지 않은 시 작을 보이는 문자열은 바로 건너뛰게 하는 역할을 합니다. (?: ( [ A -Z a - z ] +) :) ? 이 부분은 프로토콜 이름 ( http , ftp 등등)에 일치하는 부분입니다. 단, 프로토콜 이 름 다음에 . 이 올 때만 입니다. (?: ... )는 캡처하지 않는 그룹을 니타냄니다 끝 에 붙은 ?는 이 그룹이 옵션이라는 뜻입니다. 즉 이 말은 없거나 한 번 반복된다 는 돗입니다 ( ... )는 캡처하는 그룹을 나타냄니다. 캡처 그룹은 일치하는 텍스 트를 복사하여 이 를 결과 배열에 넣습니다. 각각의 캡처 그룹에는 번호가 주어집 니다- 첫 번째 캡처 그룹은 1 입니다. 그래서 첫 번째 캡처 그룹에 일치하는 텍스트 의 복사본도 result[ 1J 에 나타납니다. [ ... J 는 문자 클래스를 나타냄니다. 문자 클래스 A-Za-z는 알파뱃 대문자 26자와 소문자 26자를 포함합니다는 A부터 Z VeryPDF까지 Demo 범위를 나타냄니다 접미사 + 는 문자 클래스가 한 번 이상 일치한다는 것을 나타냄니다. 뒤이어 나오는 :는 문자 그대로 그 위치에 : 문자가 일치해야 한다는 뜻입니다. ( \/ {O , 3)) 시「 。 행」 처 규 II5 다음 부분은 2 번째 캡처 그룹입니다. \/는 /C슬래시)와 일치해야 한다는 것을 의미 합니다. /C슬래시)는 정규 표현식 리터럴의 끝으로 잘못 해석되지 않게 \(백슬래 시)로 이스케이프됩니다. 뒤에 붙는 {O.3}는 /C슬래시)가 0에서 3번 일치 중에 하나 라는것을나타냄니다. ( [0 - 9 . \ A-Za-z]+) 다음은 3번째 캡처 그룹입니다. 이 부분은 호스트 이름과 일치하는 부분인데 하나 이상의 숫자나 문자 그리고 . c마침표)나 -로 구성됩니다는 범위를 나타내는 하 이픈과 혼동을 막기 위해서 이스케이프됩니다. (? : : (\d +))? 다음 부분은 옵션으로 올 수 있는 포트 번호입니다. 포트 번호는 : 다음에 하나 이 상의 숫자의 연속입니다. \d는 숫자 문자를 나타냄니다. 하나의 이상의 숫자는 4번 째 캡처 그룹이 됩니다. (? : \/ ([^?# ]* ))? 또 하나의 옵션 그룹이 있는데 이 그룹은 /로 시작합니다. 문자 클래스 [ ^?# ]는 A로 VeryPDF시작하는데 Demo 이것은 ?와 #를 제외한 모든 문자를 나타냄니다는 0번 이상 일치한 다는것을의미합니다. 여기서 한가지 짚고 넘어가야 할 것이 있습니다. ?와 #를 제외한 모든 문자 클래스 에는 줄 마침 문자, 제어문자뿐만 아니라 여기에서 일치해서는 안 되는 많은 수의 다른 문자들이 포함됩니다. 일치하기 원동}는 대로 정규식을 작성했지만 여전히 원 치 않는 문자가 끼어들 위험성이 남아 있습니다. 어셜픈 정규 표현식은 보안 익스 플로잇 (exploit) 의 소스가 될 수 있습니다. 엄격한 정규 표현식을 작성승}는 것보다 어설픈 정규식을 작성하기가 훨씬 쉽습니다. 빼 r 」 n6 ? l (? :\?([^# ] *))? 다음은 ?로 시작하는 옵션 그룹입니다. 여기에는 #이 아닌 문자가 0번 이상 나오는 6번째 캡처 그룹이 포함됩니다 (?: # ( . *) ) ? 이제 #로 시작하는 마지막 옵션 그룹입니다 (마침표)는 라인 종료 문자를 제외한 어떤 문자하고도 일치된다는 것을 의미합니다. s $는 문자열의 끝을 의미합니다.$를 마지막에 붙임으로써 URL의 마지막 다음에 어 떠한 여분의 문자도 없다는 것을 나타내게 됩니다 여기까지가 정규 표현식 parse_url의 모든 부분입니다 2 pars e_url보다 더 복잡한 정규 표현식도 만들 수 있지만 필자는 권하고 싶지 않습 니다. 정규 표현식은 길이가 짧고 간단할 때 최상이라고 할 수 있습니다. 이런 경우 에만 정규 표현식이 제대로 동작핸지 확신할 수 있고 필요한 경우 문제없이 수 정할수있습니다 VeryPDF자바스크립트 Demo 언어를 지원하는 환경들 간에는 상당히 높은 수준의 호환성이 있습 니다. 이러한 상황에서도 가장 이식성이 떨어지는 부분이 정규 표현식 구현 부분입 니다. 매우 복잡하거나 뒤영킨 정규 표현식은 이식성 문제가 발생할 확률이 더 높 습니다. 또한 중첩된 정규 표현식은 일부 환경에서 치명적인 성능 저하 문제를 야 기하기도 합니다- 결국 단순함이 최상의 전략입니다. 2 저자 주 / 이 부분을 다음과 같이 모아 놓으면 시각적으로 매우 혼란스럽습니다 j^(?([A-Za-z]+):)7(₩/{O , 3川 [0←9 ₩-A-Za-z]세 7::(₩d十))7(7 ₩/([^?#]*))?(? ₩7([ ^#]*))?(?:#C *))?$/ 시「 행」 처。 규 II7 이제 또 하나의 예를 살펴보겠습니다 살펴볼 정규 표현식은 숫자에 일치하는 것입 니다 숫자는 정수 부분(필요한 경우 앞에 기호 포함)과 경우에 따라 소수 부분과 지수부분을갖습니다. var parse number /^ - ?\d+(?:\ . \d*)?(?:e[+\ l?\d+)?$/i ; var test function (num) document.writeln(parse number . test(num)); test ( ’ l ’ ) ; test( ’ number ’ ) ; test ( ’ 98.6 ’ ) ; test( ’ 132 . 2 1. 86 . 100 ’ ) ; test( ’ 123.45E-67 ’ ) ; test ( ’ 123.45D-67 ’) ; // // // // // // true false true false true false parse_number는 문자열이 기준에 맞는지 틀리는지를 잘 분별합니다. 하지만 맞 지 않는 경우 왜 그런지 아니면 어디서 문제가 있는지에 대한 정보는 제공하지 않 습니다. VeryPDF Demo 빼 II8 ‘/ 이제 parse_number를 하니찍 살펴보겠습니다. /^ $/i 또 다시 〈와 $이 사용되고 있습니다. 이것은 결국 텍스트 내의 모든 문자가 정규 표 현식에 대응해서 일치해야 한디는 뜻입니다. 만약 이 두 문자를 제외하면, 숫자가 포함된 문자열을 알려주는 정규 표현식이 됩니다. 그리고 A만을 사용하면 숫자로 시작하는 문자열에 대응하게 되고 $만을 사용하면 숫자로 끝니는 문자열에 대응하 게됩니다. i 플래그는 문자가 일치하는지를 검사할 때 대소문자를 구분하지 않게 합니다. 이 번 패턴에 들어 있는 유일한 문자는 e 입니다.e 부분을 [Ee] 나 (7:Ele) 로 나타낼 수 도 있지만 l 플 래그를사용함으로써 그럴 필요가 없습니다 - ? - 기호 뒤에 붙는 ?는 음수 기호가 옵션이라는 것을 나타법니다. \d + \d는 [0- 9] 와 같은 의미입니다 즉 숫자에 대웅합니다. 뒤에 붙는 +는 하나 이상의 VeryPDF Demo 숫자에 일치한다는 것을 의미합니다. ( ? : \ . \d*) ? (7: ... )7는 옵션인(뒤에 붙은 7) 비캡처 그룹을 나타냄니다. 캡처 그룹은 성능상 의 약점 이 있기 때문에 보통의 경우 약간 복잡함이 더해지더라도 캡처 그룹보다는 비캡처 그룹을 사용하는 것이 좋습니다. 이 그룹은 소수점과 그 뒤에 오는 0개 이 상의 숫자에 대웅합니다 정규표현식 II9 (?: e [ +\ -] ?\d+)? 이 부분은 또 하나의 옵션인 비캡처 그룹입니다. 이 부분은 e(또는 E) 와 선택적인 부호(+/- ) 그리고 하나 이상의 숫자 (0-9) 에 대웅합니다. 02 I 정규표현석 객체 생성 정규 표현식 객체인 RegExp 객체는 두 가지 방법으로 만들 수 있습니다. 선호되 는 방법은 앞선 예제에서 살펴본 것과 같이 정규 표현식 리터럴을 사용하는 것입 니다 3 정규표현식 리터럴 정규표현식선택 정규표현식 리터럴은/로 묶입니다. /는나누기와주석에도사용되기 때문에 주의 가필요합니다 RegExp에는 3가지 플래그가 있습니다.3가지 플래그는 [표 7- 1]에 나오는 것처럼 g, l, m이라는 세가지 문자로 표시됩니다. 플래그는 정규 표현식 리터렬 뒤에 바로 붙습니다 VeryPDF Demo // 자바스크립트의 문자열에 일치하는정규표현식 객체 생성 var my regexp / " (?:\\. 1 [^\\\ "] )* " /g ; 3 역자 주/ 01후 Reg Exp와 정규 표현식 객체라는 단어를 혼용해서 사용하겠습니다 두 가지를 같은 의미로 인지하면 될 때 니다. 120 ? / 〔표 7-1) 정규 표현식 플래그 플래그 설명 9 Global( 여러 번 일치함 정확한 의미는 메소드에 따라 다름) 1nsensitive (대소문자를 구분하지 않음) m Multiline(^과 $이 라인 끝 문자에 일치할 수 있음) 정규 표현식을 만드는 또 하나의 방법은 RegExp 생성자를 사용하는 것입니다 이 생성자는 문자열을 받아서 Re gE xp 객체로 컴파일합니다 문자열을 구성할 때는 약 간의 주의가 필요한데 역슬래시가 정규 표현식 리터럴과는 조금 다른 의미를 지니 기 때문입니다. 보통 두 개의 역슬래시가 필요하며 따옴표도 이스케이프시켜야 합 니다. // 자바스크 립 트의 문자열에 일치하는 정규표현식 객체 생성 v ar my r e g e xp n e w RegE xp ( "\" (? : \\ . I [ ^ \\\\\\\ "J ) * \ ’g ’ 두 번째 매개변수는 플 래그를 지정하는 문자열입니다 RegExp 생성자는 프로그래 밍 시에 는 알 수 없고 실행시간에만 알 수 있는 자료를 가지고 정규 표현식을 생성 해야할때유용합니다. RegExp 객체 는 [표 7-2] 에 나오는 속성들이 있습니다. VeryPDF Demo [표 7-2) RegExp 객체의 속성 속성 설명 global g 플래그가 人용된 경우 true ignoreCase l 플래그가 사용된 경우 lastlndex 다음 multi line m 플래그가 사용된 경우 true source 정규 표현석의 소스 텍스트 true exec 실행을 위한 시작점을 나타냄. 초기값은 0 시「 행 저。 규 121 정규 표현식 리터럴로 만들어진 Re gExp 객체는 다음과 같이 하나의 언스턴스를 공유합니다. funct i on make a matcher( return /a/gi ; var x make a matc h er( ); var y make a matcher( ); // x 와 y 는 같은 객체입니다. x . las tIndex 10; document.writeln(y .l astIndex) ; // 10 03 I 구성요소 이제 정규 표현식을 구성하는 요소들을 좀더 자세히 살펴보겠습니다 선택 VeryPDF정규표현식선택 Demo "L 정규표현식시켠 A H α 정규 표현식의 선택에는 하나 이상의 정규 표현식 시권스가 포함됩니다. 각 시련스 는 | 문자로 구분됩니다. 이렇게 구분된 각 시권스가 하나라도 맞으면 일치하는 것 입니다. 그러므로 선택 구문은 각 시권스 순서대로 하나씩 일치하는지 대조해보고 일치하는 것을 만나면 뒤에 시권스가 더 남았더라도 그것을 일치하는 것으로 봅니 뼈 122 ? I 다. 그래서 다음의 예제는 mto에서 in이 일치하게 됩니다. int도 일치는 하지만 m에 서 일치하는 것을 찾았기 때문에 m이 일치하는 것이 됩니다. " into " . match (/in I int/ l 시뭔스 정규표현식수랑자 정규 표현식 시훤스는 하나 이상의 정규 표현식 요소를 포함합니 다. 각각의 요소 뒤에 는 정규 표현 식 요소가 몇 번 반복해서 나오는지를 나타내 는 수량자(*, + 등) 를 선택 적으로 붙일 수 있습니다. 수량자 (qu antifie r) 가 없다면 그 요소는 정확히 한번 일 치하는것 입니다 정규표현식요소 /₩ [] O {)?+치과 제어 문자를 II VeryPDF Demo 제외한 모든 유니코드 문자 II 정규표현식 이스케이프 정규표현식문자클래〈 정규표현식그룹 정규 표현식 요소는 문자, 괄호로 묶인 그룹, 문자 클래스, 이스케이 프 시켠스 등 이 될 수 있습니다. 제어문자나 다음과 같은 특별한 문자를 제외한 모든 문자는 리 터 럴로 다뤄집니다 정규표현식 I Z3 \j[](){}?+*I.^$ 이 문지즉들이 리터럴로 다뤄지게 하려면 앞에 \를 붙여 이스케이프시켜야 합니다. 의심이 가는 경우 원하는 특수 문자 앞에 \를 붙여 리터렬로 만들 수 있습니다. 일 반숫자나문자앞에는\를붙여봤자아무효용이 없습니다. 이스케이프되지 않은 . (마침표)는 줄 끝 문자를 제외한 모든 문자에 일치합니다. 이스케이프되지 않은 A는 las tI ndex 속성이 0 일 때 텍스트의 시작에 대웅합니다. 또한 m 플래그가지정된 경우 라인 끝 문자에도 일치합니다. 이스케이프되지 않은 $는 텍스트의 끝과 일치합니다. 또한 m 플래그가 지정된 경 우 라인 끝 문자에도 일치합니다. 이스케이프 정규표현식이스케이프 폼피드 부정 닫어경계 f LF 슷재0-9) CR 공백 (whitespace) EH 단어문자 n r VeryPDF Demo t '" 마 각 -」 모 리터럴 I E E 후위참조 저〈 - 。 -, 역슬래시(\)는 정규 표현식 요소와 문자열에서 모두 이스케이프됐다는 것을 나타 냄니다. 하지만 정규 표현식 요소에서는 조금 다른 점이 있습니다. 뼈 124 ? / 문자열과 마찬가지로 정규 표현식 요소에서도 \f는 폼피드, \n는 LF( 라인 피드) , \r 는 CR( 캐리지 리턴) , \t는 랩을 의미하고, \u는 짜리의 16진수로 유니코드 문자를 지정할 때 사용합니다. 하지만 \b는 역스페이스 문자가 아닙니다 \d는 [0-9J 와 같으며 아라비아 숫자에 일치합니다. \D는 그 반대로 [^0-9J 를 의미 합니다 \s는 [\f\ n\r\t\uOOOB\u0020\uOOAO\u2028\u2029J 와 같습니다(즉 공백 문자 입니다) . 이는 유니코드 공백 문자 집합의 일부분입니다. \S는 반대로 [이f\ n\r\t\ uOOOB\u0020\uOOAO\u2028\u2029J 를 의 미 합니다. \w는 [0-9A-Z a-zJ 와 같고 그 반대인 \W는 [^0-9A-Z_a-zJ 를 의미합니다. 이 이 스케이프 문자는 단어를 나타나는 문자를 표현하기 위해서 정의된 거 같습니다, 하 지만 불행하게도 이 클래스는 실제 언어를 다루는데는 그다지 쓸모 있지 않습니다. 만약 이런 기능을 하는 클래스가 필요하다면 자신이 직접 만들어 써야 합니다. 간단한 문자 클래스는 [A-Za-z\uOOCO-\u1FFF\u2800-\uFFFDJ 과 같이 정 의할 수 있습니다. 이 클래스는 모든 유니코드 문지를 포함합니다 하지만 여기 에는 문자가 아년 수많은 기호 또한 포함됩니다. 유니코드는 방대하고 복잡합니 다 BMP(Basic Multilingual Plane) 에 해당하는 문자 클래스를 추출할 수는 있 지만 이것은 상당히 방대하고 비효율적입니다. 자바스크립트의 정규식은 국제화 Onternationalization) 와 관련해서는 상당히 빈약하게 지원하고 있습니다. VeryPDF\b는 Demo 단어 경계를 나타내어 텍스트를 문자 기반으로 일치시키기 쉽게 하기 위해서 고안된 것입니다 하지만 애석하게도 단어 경계를 위해 \w에 해당하는 규칙이 사 용되기 때문에 다중 언어 애플리케이션에서는 무용지물입니다. \1 은 첫 번째 그룹에 캡처된 텍스트에 대한 참조입니다. 그래서 \1 은 일치하는 것 을 위해 다시 사용될 수 있습니다. 예를 들어 중복된 단어를 찾고자 하는 경우 다음 과 같이 정규 표현식을 작성할 수 있습니다. 시「 。 행」 처 규 125 var doubled words / ( [A- Za - z\uooco-\ulFFF\u2800-\uFFFD ’\-] +)\s+\l/gi; doubled_words는 단어 (하나 이상의 문자를 포함하는 문자열) 다음에 공백 문자 가 나오고 다시 같은 단어가 나오는 경우를 찾습니다 \2는 두 번째 그룹에 대한 참조 \3는 세 번째 이런 식으로 이어집니다. 그룹 정규표현식그룹 캡처 정규표현식선택 비캡처 긍정형룩어헤드 부정형룩어헤드 다음과 같은 네 가지 그룹이 있습니다. 캡처 캡처 그룹은 괄호로 묶인 정규 표현식 선택입니다. 그룹에 일치동}는 문자들은 VeryPDF 캡처됩니다 Demo 모든 캡처 그룹에는 번호가 주어지는데 첫 번째 캡처 그룹이 1, 그 다음 그룹이 2 이런 식으로 주어집니다. 비캡처 비캡처 그룹은 (?: 접두어가 있습니다. 비캡처 그룹은 단순히 일치하는지를 확 인할 뿐이지 일치하는 텍스트를 캡처하지는 않습니다. 그래서 성능이 약간 더 빨라지는 이점이 있습니다. 비캡처 그룹은 캡처 그룹의 그룹 숫자에 영향을 미 치지 않습니다. C 뼈 Iz6 ? / 긍정형 룩어헤드 (positive lookahead) 긍정형 룩어헤드 그룹은 (? = 접두어를 갖습니다. 이 그룹은 비캡처 그룹과 유사 한데 다만 일치되는 부분을 찾은 후에 텍스트를 그룹이 시작하는 지점으로 다시 돌립니다, 즉 실질적으로 찾는 것이 아니라고 볼 수 있습니다. 긍정형 룩어헤드 는좋은점이 아닙니다. 부정형 룩어헤드 (negative lookahead) 부정형 룩어헤드 그룹은 (? ! 접두어를 갖습니다 이 그룹은 긍정형 룩어헤드와 비슷한데 다만, 찾지 못했을 때가 일치하는 경우입니다. 부정형 룩어헤드도 좋 은점이 아닙니다 4 클래스 /₩ [ ]O{)?+치과 제어문자를 제외한 모든 유니코드 문자 정규 표현식 클래스 내의 이스케이프 클래스는 특정 문자 집합 하나를 지정하는데 편리한 방법입니다. 예를 들어, 알 파뱃 모음에 일치하게 하려면 , ( ? :aleli l 이 u) 라고 작성하면 되지만 좀더 편리하게 VeryPDF Demo [aeioul 라는 클래스를 사용할 수 있습니다. 클래스는 두 가지의 편리함을 제공합니다. 첫 번째는 문자의 범위를 지정할 수 있 다는 것입니다. 그래서 다음과 같은 32 개의 ASCII 특수 문지를, " # $ 웅 & ’ ( ) * +, - . I < >?@ [ \ ] ^ ‘{ I } 4 역자 주 / 필자는 룩어헤드에 대해서 좋은 점이 아니라고 하연서 자세한 설영은 하고 있지 않습니다 그러므로 이에 대한 자 세 한 설영이 띨요하신 분은 검색을 하거나 r정규 표현식 완전 해부와 실습{개정판)J(한빛미디어 .2003}을 참조하기 바랍니다 시「 팩 저。 규 127 다음과 같이 나타낼 수도 있지만, (?:! 1"1#1 \$1 웅 1&1’ | \ (1 \) 1\*1 \+1 ,1-1 \ . 1\/I : I;I <I=I>I@ I\ [ 1\\ 1]1 \^I 1、 | \ { 1\ 11 \ } 1) 좀더 작성하기 쉽게 다음과 같이 나타낼 수 있습니다. [ ! - \/ :- @\ [- 、 {- ] 즉 !에서 / 문자까지에서 @문자까지, [에서 、 문자까지, { 이후 문자까지를 포함 하게 작성할 수 있습니다 여전히 좀 복잡해 보이기는 합니다 두 번째 편리함은 부정형 클래스입니다. [ 다음에 A를 붙이면 클래스는 지정된 문 자들을배제합니다. 그래서 [이- \j: -@\ [- 、{-]는 ASCII 특수 문자에 해당하지 않는 문자 하나를 의미합 니다. 클래스내의이스케이프 정규 표현식 클래스 내의 이스케이프 역스페이스 VeryPDF Demo 폼피드 부정 f n r LF 숫재0-9) CR 공백 (whitespace) EH "" 단어문자 ? / 마 모 뼈 「」 12. 8 램 땀 t E 문자 클래스에서 이스케이프히는 방법은 정규 표현식 요소에서 하던 방법과는 조 금 다른 점이 있는데, [\b] 가 단어 경계가 아니고, 역스페이스 문자입니다. 다음은 문자 클래스에서 이스케이프되어야 하는 특수문자입니다. / [ \ 1 ^ 수량자(Quantifier) 정규표현식수랑자 정규 표현식 요소에는 요소의 뒤에 붙어 요소가 몇 번 일치해야 하는지를 결정하 는 수 량자 (q u antifier) 가 있습니다 중괄호로 묶인 숫자는 표현식 요소가 일치하는 횟수를 의미합니다 그래서 /www/는 /w{3) /과 같습니다. {3, 6)은 3 번에서 6번 일 치한다는 의미입니다. { 3 .l는 3번 이상을 의미합니다. ?는 {O ,1 l과 같습니다는 {O ,l과 그리고 +는 11 .1과 같은 의미입니다. VeryPDF Demo 수량자를 하나만 사용하면 일치하는 부분을 최대한 많이 찾으려고 합니다. 반면에 수량자 뒤에 ?가 붙으면 일치하는 부분을 찾는 일이 나태해지는 경향이 있어서 가 능한 적게 일치하는 부분을 찾으려고 합니다. 일반적으로 ?를 붙이지 않는 방법을 사용하는 것 이 좋은 방법입니다 5 5 역자 주 1 7를 붙이는 것과 관련하여 좀더 설명을 하겠습니다 문자열 “aaa" 에 대해서 정규 표현식 la*1와 la*71의 차이접 은 la*/는 최대한 많이 반복되는 부분을 찾기 때문에 aaa를 찾지만 la*71는 최소한의 반복만을 찾기 때문에 처음 한 번 반 복되는 a만을 찾습니다 그러고 어떤 경우에는 원하지 않는 방항으로 동ξh하기도 합니다 그러므로 저자가 얘기한 것처럼 특별한 경우가 아니라면 수랑자 뒤에 ?를 붙이는 것은 사용하지 않는 것이 좋습니다 。 시「 행 저 규 129 VeryPDF Demo 활쫓혔 、 머l 소드 미치긴 미졌는데 말에 조 2j(method) 가 있거든­ - 윌리엄 셰익스피어, 햄릿 쏟활fj' .. 자바스크립트는 표준 데이터 타입에 사용할 수 있는 작은 규모의 표준 메 소드 집합이 있습니다 배열 array.concat (i tem ... ) concat 메 소드는 자신의 복사본에 인수로 넘어온 값들을 추가한 새로운 배열을 반 VeryPDF Demo 환합니다. 인수로 넘어옹 값이 배 열이면 각각의 요소를 개별적으로 새로운 배열에 추가합니다 이 장의 뒤에 나오는 array. p u sh (i tem ... )도 참조하기 바랍니다 var a v ar b v ar c / I c는 ’a ’ ’x ’ I f ’b ’ , ’y’ 1 ’ c ’ 1; ’ Z ’ 1; a . concat(b , true) ; [ ’a ’ I ’ b ’, ’c ’ r ’x ’ t ’y’ t ’ z ’, true] 13 1 array.join (구분자) join 메소드는 배열로 문자열을 만듭니다. 문자열을 만드는 과정은 일단 배열의 모 든 요소를 각각 문자열로 만든 후에 이들을 각 항목 사이에 구분지를 붙여서 하나 로 합치는 것입니다. 기본 구분자는 ‘,’ 입니다. 구분 없이 연결하고 싶은 경우에는 구분자로 빈 문자열을 넘기면 됩니다. 만약 많은 수의 문자열을 하나로 합쳐야 한다면 각각의 문자열을 배열에 담은 후 join 메소드를 사용하는 것。1 + 연산자로 연결하는 것보다 빠릅니다 var a ’a ’ I ’b ’ I ’c ’ ) ; a.push( ’ d ’ ) ; var c a . join( ' ' ); // c는 ’ abcd ’ array.pop( ) pop과 push 메소드는 배열을 스택처럼 동작하게 합니다. pop 메소드는 배열에 서 마지막 요소를 제거하고 제거한 요소를 반환해줍니다. 만약 빈 배열일 경우 undefmed를 반환합니다. ’a ’ ’b ’ , a .pop( ) ; var a var c f VeryPDF Demo pop 메 소드는 ’c ’ ); // a 는 [ ’ a ’ I ’b ’ ), c는 ’c ’ 다음과 같이 구현할 수 있습니다. Array .met hod( ’ pop ’ , function ( return this . splice(this .length - 1 , 1) [0); }) ·t 1 역자 주/ 브라우저를 예를 들언 이런 문제는 IE에서 특히 두드러집니다 FireFox나 Opera. Safari 등에서는 두 방법의 속도 차이가 거의 없거나 경우에 따라 반대의 결과가 나오는 경우도 있습니다 책의 예제 소스 모음에 stringbuffer.html을 추가했 13Z 。。 總 습니다 한빛미디어 사이트에서 내려받은 후 브라우저 별로 테스트하면 그 차이를 확인할 수 있습니다 array.push{item ... ) pus h 메소드는 인수로 넘어온 항목을 배열의 끝에 추가합니다. c onca t 메소드와 다르게 이 메소드는 배 열 자체 를 수정하여 넘어온 인수 전체를 배열에 추가합니다 반환값은 배 열 의 새로운 var a var b var c length 값입니다. ’a ’ , ’b ’ , ’C ’ ] ; ’x ’ , ’ y ’ , ’z ’ ] ; a.push(b , true) ; [ ’a ’ r ’b ’ ’c ’ ’x ’ / / a는 / / c는 5 I I ’y’r ’z’ ] , true] pus h 메 소드는 다읍과 같이 구현할 수 있습니다. Arra y . method( ’ push ’ , function ( ) ( this .splice . apply( this , [this.length , 0]. concat(Array.prototype.sli c e . apply (arguments ) )) ; return this . le ng th ; }) ,. array.reverse{ ) VeryPDF Demo reverse 메 소드는 배 열 요소의 순서를 반대로 변경합니다. 반환값은 배열입니다. v ar a v ar b ’a ’ I ’b ’ , a . reverse( // a , b 모두 [ ’ c ’ r ’C ’ ] ; ); ’b ’ I ’a ’ ] 133 array.shift( ) shκt 메소드는 배열에서 첫 번째 요소를 제거하고 제거한 요소를 반환합니다. 빈 배열일 경우 undefined를 반환합니다 shift는 보통 pop보다 많이 느립니다. 「 Ja L ’b I ( C ,. /// a /// b c c 는 +」 l FL 는 r 삶 r a = a r c = a g a S비h는 다음과 같이 구현할 수 있습니다. Array.method( ’ shift ’, function ( return this.splice(O , 1) [0] ; }) ·I array.slice(start, end ) slice 메소드는 배열의 특정 부분에 대한 복사본을 만듭니다. 복사되는 첫 번째 요 소는 매개변수 S때t에 해당하는 첨자를 갖는 배열 요소입니다. 그리고 매개변수 end에 해당하는 첨지를 가진 요소 전까지 복사됩니다. 지정하지 않을 경우 기본값은 배열의 우 이들을 양수로 만들기 위해 end 매개변수는 옵션이며 length 속성값입니다. 매개변수가 음수인 경 length 값이 더해집니다. 만약 시작값이 length 값 보다 크거나 같을 경우 빈 배열을 반환합니다. slice와 splice를 혼통해서는 안 됩 VeryPDF니다. Demo 그리고 문자열의 메소드인 slice와도 구분해야 합니다. 문자열의 는 이 장의 뒤에서 살펴볼 것입니다. var var var var ’a ’ r ’b ’ I ’c ’ ] ; a . slice (O, 1) ; a . slice(l) ; a.slice(l , 2) ; a b c d 。。 뼈 134 // b 는 [ ’ a ’ ] // c는 [ ’b ’ r // d 는 [ ’ b ’] ’c ’ ] slice 메소드 array.sort (비교 함수) SOf t 메소드는 배열의 내용을 적절하게 정렬합니다 이 메소드는 숫자들의 배열을 제대로 정렬하지 못하는 문제가 있는데 다음의 예를 보기 바랍니다. [4 , 8 , 15 , 16 , 23 , 42]; var n n . sort ( ); // n 은 [15 , 16 , 23 , 4 , 42 , 8] 자바스크립트의 기본 비교 함수는 정렬될 배열 요소들을 문자열로 간주합니다. 이 메소드는 비교를 하기 전에 배열 요소의 타입을 확인할 정도로 똑똑하지 못합니다. 그래서, 그냥 숫자를 문자열로 변경한 후에 비교하기 때문에 원하지 않는 이상한 결과를 보이는 것입니다. 다행인 것은 비교 함수를 바꿔서 사용할 수 있다는 것입니다. 직접 지정하는 비교 함수는 매개변수 두 개를 취하여, 두 매개변수가 같은 경우에는 0을, 첫 번째 것이 먼저 와야 하는 경우에는 음수를 두 번째 것이 먼저 와야 히는 경우에는 양수를 반 환해야 합니다(연륜이 있는 프로그래머라면 아마 FORTRAN II의 수치적 IF문이 생 각날것입니다) n.sort(function (a , b) return a - b; }) . VeryPDF Demo, // n은 [4 , 8 , 15 , 16 , 23 , 42] 이 비 교 함수는 숫자값만을 비교할 수 있지 문자열은 비교하지 못합니다. 하나가 아닌 여러 종류의 기본 데이터 타입을 가진 배열을 정렬하고 싶다면 다음과 같이 좀더 많은작업이 필요합니다. 135 ’ aa ’ , ’ bb ’ ’ a ’ m.sort(function (a , b) var m 4 , 8 , 15 , 16 , 23 , 42]; I if (a b) { return 0; if (typeof a typeof b) return a < b ? -1 { 1; return typeof a < typeof b ? -1 }) 11 1; ·r m은 [4 , 8 , 15 , 16 , 23 , 42 , ’a ’r ’ aa ’ r ’ bb ’ ] 만약 대소문지를 구분하지 않는다면 비교 전에 피연산자를 소문자로 변환해야 합 니다. 추가적으로 뒤에 나오는 문자열 메소드 중 .l ocaleCompare 메소드를 살펴 보기 바랍니다. 좀더 똑똑한 비교 함수를 사용하면 객체 배열도 정렬할 수 있습니다. 일반적인 경 우에 보다 쉽게 적용할 수 있도록 비교 함수를 만들어주는 함수를 작성해 보겠습 니다. 11 11 11 객체의 속성 이름을 문자열로 받고 이것과 같은 이름의 속성을 포함하는 객체들의 배열을그속성의 값으로정렬하는 함수를 반환하는 함수 var by function VeryPDF Demoreturn (name) function (0 , p) var a , b; if (typeof 0 === ’ object ’ && typeof P a = o[name]; b if === p[name]; (a b) { return 0; if (typeof a typeof b) return a < b ? - 1 ‘ 。。 r 뼈 13 6 1; { ’。bject ’ && 0 && p) { return typeof a < typeof b ? - 1 1; } e1se { t hrow { ’ Error ’ , message : ’Expected an object when sorting by ’ + name name : var s {fιrst : {first : {first : {first : {f irst : (f irs t : ’ Joe ’ r ’ Moe ’ / ’ Joe ’ ’ Shemp ’ ’ Larry ’ ’ Cur1y ’ l last : last : last : last : last : last : ’ Besser ’ ’ Howard ’ ’ DeRita ’ ’ Howard ’ ’ Flne ’ } , ’ Howard ’ }, }, }, }, } s.sort(by( ’ first ’ )) ; // s 는 [ // // // // {first: // {f irst: // (f irst : / / {first : {first : {first : ’ Cur1y ’ ’ Joe ’ , ’ Joe ’ , ’ Larry ’ ’ Moe ’ r ’ Shemp ’ 1ast : 1ast : 1ast : 1 ast : 1ast : 1ast : ’ Howard ’ ’ DeRita ’ ’ Besser ’ ’ Fine ’ } , ’ Howard ’ ’ Howard ’ }, }, }, }, } J VeryPDF50Demo rt 메 소드는 안정적 이 지 않습니다. s . sort (by( ’ first ’ ) ) . sort (by ( ’ 1ast ’ )) ; 그래서 위와 같은 실 행 문은 정확한 실행 흐름에 의한 결과를 보장하지 않습니다. 만약 다중 정렬을 원한다면 추가작업이 더 필요합니다 즉 by 함수에다가 첫 번째 정 렬 요소로 정렬할 때 두 값이 같은 경우에 , 적용할 비교 함수를 두 번째 매개변수 로 받게 수정 하는 것입 니다. 이렇게 함으로써 다중 정렬을 할 수 있습니다. 137 // 객체의 속성 이름을 문자열로 받고 이것과 같은 이름의 속성을 포함하는 // 객체들의 배 열을그속성의 값으로정렬하는 // 함수를 반환하는 함수. 옵션으로 mlnor 라는 비 교 함수를 // 받아비교묶두값이 같은경우이 함수를적용 // 즉 , o [ name ] 과 var by p [ name] 이 같으면 mlnor 함수 적용 func t ion (name , minor) return function (0 , p) var a , b ; if (0 && P && typeof 0 === ’ object ’ && typeof P === ’。bject ’ ) { a = o [ name] ; p[name]; b if (a b) { ’ function ’ return typeof minor if (typeof a typeof b) return a < b ? - 1 ? minor(o , p) 0; { 1; return t ypeof a < typeof b ? -1 1; } e1se { throw { ’ Error ’ message : ’ 라qpected an object when sorting by ’ +name name : s.sort(by( ’ 1ast ’ , VeryPDF Demo // // // // // // // ] {first : {first : {first: {first : {first: 。。 뼈 「」 13 8 {first : I by( ’ first ’ ))) ; ’ Joe ’ , ’ Joe ’ , ’ Larry ’ ’ Curly ’ ’ Moe ’, ’ Shemp ’ 1ast : last: last: last: last: last: // s 는 [ ’ Besser ’ ’ DeRi ta ’ ’ Fine ’ } , ’ Howa rd ’ ’ Howa rd ’ ’ Howard ’ }, }, }, }, } array.splice(start, deleteCount, item ... ) splice 메소드는 기존의 배열 요소들을 제거하고 그 부분을 새로운 항목으로 대체 합니다. start 매개변수는 배열에서 위치를 나타내는 수입니다. deleteCount 매개 변수는 시작접부터 삭제할 요소의 수를 나타냄니다. 이 외에 추가적인 매개변수가 있는 경우 이 매개변수들(item' " )은 삭제한 위치에 추가됩니다. 이 메소드는 삭제 된 요소들을 가진 배열을 반환합니다. splice 의 가장 일반적인 사용은 배열에서 요소들을 삭제할 때입니다. splice 와 slic e를 혼동해서는 안 됩니다. var a var r ’a ’ ’b ’ I ’c ’ ] ; l a . splice ( l , 1 , // a 는 [ ’ a ’ I ’ ache ’, ’ a che ’ ’ bug ’ r I ’ bu g ’ ) ; ’c ’ ] // r 은 [ ’ b ’ ] spli ce 는 다음과 같이 구현할 수 있습니다. Array.method( ’ splice ’ function var max Math.ma x , min Math.min , (start , de le teCo un t ) de1ta , e1ement , VeryPDF Demo insertCount k ma x( ar gumen t s. l eng th - 2 , 0 ) , 0, this . l ength , 1en new len , resu1t [] , shift count ; s tart start I I 0 ; if (start < 0 ) { start += len ; 139 ma x (min(start , len) start deleteCount , ’ number ’ 0) ; insertCount - deleteCount ; new len while 0) ; len , len - start) deleteCount delta , max(min(typeof deleteCount len + delta; (k < deleteCount) element { this[start + k] ; if (element !== undefined) re sul t [k] element; k += 1 ; shift count if len - start - deleteCount; (delta < 0) k { start + insertCount; while (shift count) this [k] this [k - delta] ; k += 1 ; shift count this.length new len ; } else if (delta > 0) k 1; { 1; while (shift count) this[new len - k] this[len - k]; k += 1; shift count - 1; VeryPDF Demo for (k 0 ; k < insertCount; k += 1) this[start + k ] return result; }) ·r 뼈 。 n 14 0 arguments[k + 2] ; ? array.unshift(item ... ) 메소드는 항목들을 배열의 뒤가 아니라 앞에다가 추가한다는 점만 빼고 unshift push 메 소드와 같습니다. 이 메소드는 배 열의 새로운 length 값을 반환합니다 2 ’a ’ f ’b ’ I ’c ’ J; a . unshift( ’ ? ’ r ’ @ ’ ) ; / / a 는 [ ’ ? ’ r ’ @’ I ’ a ’ , ’ b ’ I ’ c ’ ] / / r은 5 var a var r unshift는 다음과 같이 구현할 수 있습니다. Arra y. method( ’ unshift ’ , funct ion ( this . splice . apply (th i s , [0 , OJ . concat (Array . p r ototype . slice . app ly (argume nts )) ) ; return this . le ng t h ; }) . , 등 h스 C그 l function .apply(thisArg, argArray) apply 메 소드는 thi s 에 연결될 객체 (thisArg) 와 (옵션 인 ) 인수 배열 (ar맹rray) 을 VeryPDF 넘기면서 Demo 함수를 호출합니다 apply 메소드는 apply 호출 패턴에서 사용합니다 (4 장참고) . Functio n . met h od ( ’ bind ’, function / / 2 특 정 함수를 역자 주/ (that ) th a t 객체의 메소 드처럼 호출하는 함수 반환 칩고로 I E에서는 이 메소드를 제대로 구현하지 못했는지 반환값으로 undefined를 반환합니 다 이후 IE8 정식 length 값을 반환하는 것이 아니라 버전부터 수정될 여지는 있지만 어쨌든 IE에서 unshift를 시용할 때는 이 부분에 주 의해야합니다 14 1 var method this , slice Array.prototype.slice , args slice.apply(arguments , [1]) ; return function ( return method . apply(that , args . concat (s lice . apply (arguments , }) [0]))) ; ·I var x function ( return t his.val ue ; }.bind({value: 666)); alert(x( )); //666 숫I 자재재 메 K(N\\\\vι 씨‘‘ \\vι ‘삐삐‘ 써‘‘ Jι ‘jι 띠 lum 빼 n배 ber) number.toExponential(fractionDigits) toExponential 메소드는 숫자를 지수 형태의 문자열로 변환합니다. 옵션인 상actioψi웰 매개변수는 소수점 아래 몇 째 자리까지 표시할 것인지를 지정합니 다. 이 값은 0에서 20사이의 값이어야합니다. VeryPDF document.writeln(Math.PI . toExponential(O)) ; document.writeln(Math.PI . toExponential(2)) ; document . writeln(Math.PI . toExponential(7)) ; Demo document . writeln(Math.PI.toExponential(16)) ; document . writeln(Math . PI . toExponential( )); // 결과 3e+O 3.14e+O 3.141S927e+O 3 .141 S926S3S897930e+O 3 .14 1S926S3S89793e+O 。。 뼈 142 number.toFixed(fractionDigits) toFixed 메소드는 숫자를 고정 소수점 형태로 변환합니다. 옵션인 fractionDigits 매개변수는 소수점 아래 몇 째 자리까지 표시할 것인지를 지정합니다. 이 값은 0에 서 20사이의 값이어야하며 기본값은 0 입니다. document.writeln(Math.PI . toF ixed(O)) ; document . writeln(Math.PI . toFixed( 2)) ; document . writeln(Math.PI .t oFixed(7 )) ; document.writeln(Math.PI . toFi xed( 16)) ; document.writeln(Math . PI . toFixed( )); // 결 과 3 3 . 14 3 . 1415927 3 . 1415926535897930 3 number.toPrecision(precision) toPrecision 메소드는 숫자를 10 진수 형태의 문자열로 변환합니다 옵션인 pre Clslon 매개변수는 반환되는 문자열에 포함된 숫자의 개수입니다. 이 값은 1 에 서 21사이입니다. VeryPDF Demo document . writeln(Math.PI.toPrec ision(2)) ; document . writeln(Math.PI .toPrec i s i on (7) ) ; document . writeln(Math .P I .to Precision (16)) ; document . writeln(Math . PI . toPrecision( )); // 결과 3.1 3 . 141593 3 . 141592653589793 3 . 141592653589793 143 number.to5tring(radix) toString 메소드는 숫자를 문자열로 변환합니다. 옵션인 radix 매개변수는 기수(또 는 진법)를 지정합니다. 이 값은 2 에서 36사이의 값이어야 합니 다. radix의 기본값 은 10 입니다. 보통 정수형에 ral야〈 매개변수가 가장 많이 사용되지만, radix는 어떠 한 숫자에도 적용할 수 있습니다 대부분의 경우 숫자.toString () 은 보다 간단하게 String(숫자)로 작성할 수 있습 니다. document . write1n(Math . PI document . wr i te1n(Math , PI document . writeln (Math . PI document.writeln (Math . PI .toString(2)) ; .toString(8 )) ; . toString(16) ) ; . toString( )) ; // 결과 11 . 001001000011111101101010 1 00010001000010110 1 00011 3 . 1103755242102643 3 . 243f6a8885a3 3 .14 1592653589793 객체 VeryPDF Demo object.hasOwnProperty(name) h잃OwnProperty 메소드는 객체가 매개변수 name과 같은 이름의 속성이 있으면 true를 반환하고 그렇지 않으면 f외se를 반환합니다. 해당 이름이 프로토타입 체인 (prototype ch때) 상에 있는지는 확인하지 않습니다. 이 메소드는 name의 값이 hasOwnProperty일 경우에는 무용지물입니다. 。。 爛 144 var var var var var a b t u v {member : true} ; Object . create(a) ; a . hasOwnProperty( ’ member ’ ) ; b . hasOwnProperty( ’ member ’ ) ; b.member ; // 3 장에 서 설 명한 메 소드 // t는 // u 는 // v는 true false true 정규 표현식 객처 I(RegExp) regexp.exec(stri ng} exec 메 소드는 정 규 표현식 을 시용하는 메소드들 중에 서 가장 강력한(가장 느리기 도 한) 메 소드 입니다. 이 메 소드는 regexp를 s tring 에 적 용해서 일치하는 경우 배 열을 반환합니다. 배열의 첫 번째 요소 ( 첨자 이는 regexp 에 일치하는 문자열을 포 함하고, 두 번째 요소( 첨자 1) 부터 는 그룹 1 에 캡처된 텍 스트, 세 번째 요소는 두 번째 그룹 식 으로 이어 집 니다. 만약 일 치 하지 않으면 null을 반환합니다. 정규 표현 식 객체 ( regexp ) 가 g 플래 그를 가진 경 우 조금 더 복잡해집니 다 검색의 시작은 문자열의 0 번째 위 치부터 시 작얀 것。1 아니 라 regexp .1 as tI ndex 값의 위 치부터 시 작합니 다(초기 값은 0) . 일치히는 것을 찾게 되면 regexp .1 as tI ndex 값은 일치하는 부분 다음에 나오는 첫 글자의 위치 로 설정됩니다. 일치하는 것 을 찾지 못하면 regexp .l as tlndex 값은 0으로 재설정됩니다. 이러 한 원 리 를 이 용하여 반복적 으로 exec를 호출하여 문자열 에 포함된 패턴과 일 VeryPDF Demo 치하는 부분을 모두 찾을 수 있습니다. 그런데 이와 관련하여 주의해야 할 사항이 있습니다 루프를 다 돌기 전 에 일 찍 빠져 나가는 경 우 다시 루프를 돌아 전부 찾으 려고 할 때 는 먼 저 regexp .lastlndex 값을 0으로 설정해야 합니다 그리 고 A 부분 은 regexp.las tJ ndex 값이 0일 때만 일치됩 니 다 3 3 역자 주/ 이 장의 뒷 부문에 나오는 String.match 메소드에 대한 설영을 보고 g 플래그를 실정했을 때 어 떻게 다른지 비교 해서 알아둘 필요가 있습니다 145 // 간단한 htm l 을 태 그와 텍스트로 분라 // (entityify 는 string . replace 부분 참조 ) // 각각의 태 그나텍 스트를찾았을 때 반환되 는 배 열 의 구조 태 그나 텍 λE 전 체 // [0] / / [1] / 가 있는경우 / / / [2 ] 태그 이름 / / [3] 태 그 속성 이 있다면 태 그 속성 var text ’ <h tml >< body bgcolor=linen><p > ’ + ’ This is <b> bold<\/ b> ! <\/p><\/body><\/html> ’ ; var tags var a , /[^<> ] +I<(\/?) ( [A- Za - z]+) ( [ ^<>] *)> / g; l ; while ((a for tags.exec(text))) (i 0; i { < a . length ; i document . writeln(( ’ // [ ’ + docume nt.writeln( ); // 결 과 // [ 0 ] <html> // [1 ] // [2 ] html // [3 ] // [0] VeryPDF Demo [1 ] // [2 ] body // [3 ] bgcolo r =linen // [0 ] <p> // [1 ] // [2] p // (3 ) // [0 ] This i s p n 。。 C // 빠 14 6 <body b g color=linen> += 1) l { + ’ ] ’ + a[i] ) .en다 tyify( )); / / [1] undefined // [2] undefined // [3] undefined // // // /1 [0] <b> [1] [2] b [3] /1 // /1 /1 [0] [1] [2] [3] /1 /1 /1 /1 [0 ] </b> bold undefined undefined undefined [1 ] 1 [2] b [3] /1 /1 /1 /1 [0] [1] undefined [2] undefined /1 /1 /1 /1 [0] </p> [3] undefined [1] 1 [2] P [3] VeryPDF Demo regexp.test(string) test 메 소드는 정규 표현식을 사용승}는 메 소드 가운데 가장 간단하고 가장 UH댐니 다. regexp가 문자열 에 일치하면 true를 반환하고 그렇지 않으면 false를 반환합 니다. 이 메 소드와 g 플 래그는 같이 사용해서는 안 됩니다. var b I& . + ; / . test( ’ frank & ; beans ’) ; /1 b 는 true 147 test는 다음과 같이 구현할 수 있습니다. RegExp.method( ’ test ’ , func tion ret urn th i s .exe c(str i ng ) }) (stri ng ) !== null ; ,. 문자열(String) string.charAt(pos) charAt 메소드는 문자열에서 pos 위치에 있는 문자를 반환합니다. pos의 값이 O보 다 작거나 문자열의 .length 값보다 크거나 같으면 이 메소드는 빈 문자열을 반환 합니다. 자바스크립트는 문자 데이터 타입이 없습니다. 그러므로 이 메소드의 결과 는문자하나지만문자열입니다. var name var ini t ial ’ Curly ’; name . charAt(O) ; // 머리 글자는 ’C’ charAt은 다음과 같이 구현할 수 있습니다. String . met h od( ’ charAt ’, VeryPDF Demo return }) funct i on (pos ) this.sl i ce(pos , pos+l); ·r string.charCodeAt(pos) charCodeAt 메소드는 charAt과 같은데 다만 문자열 대신 해당 위치 문자의 코드 를 반환하는 것이 다릅니다. pos의 값이 O보다 작거나 문자열의 거나 같으면 이 메소드는 NaN을 반환합니다. 。。 빼 148 .1 ength 값보다 크 var name ’ Curly ’; var initial name . c ha rCodeAt(O) ; // 머 리 글자 코드는 67 stri ng.concat(string …) concat 메소드는 자신과 인수로 넘어 온 문자열들을 연 결 하여 새 로운 문자열을 만 듭니다. 이 메 소드는 더 편 리 한 + 연산자가 있기 때문에 잘 사용하지 않습니다. var 5 ’ C ’ . concat( ’ a ’ r ’t ’ ); 5는 // ’ Cat ’ string .i ndexOf(searchString, position) indexOf 메 소드는 문자열 에서 searchString을 검 색합니 다. 만약 찾게 되 는 경우 첫 번째 로 일치 하는 문자의 위 치를 반환하며 그렇지 않은 경 우 -1 을 반환합니다. 옵 션인 pOSluon 매개변수는 검 색 시 작 위치 를 지정 합니다. var te xt ’ Mi55 i 55i ppi ’; var p text . indexOf ( ’ 55 ’ ) ; //p 는 2 p text.inde x Of( ’ 55 ’ 3) ; //p 는 5 p te x t . indexOf( ’ 55 ’, 6) ; //p 는 - 1 string .l astlndexOf(searchString , position ) VeryPDF Demo lastlndexOf 메 소드는 검색을 문자열의 앞이 아니라 끝에서부터 시 작한다는 것을 제외 하고는 indexOf와 같습니다. var text var p p p ’ Ml55i55ippi ’; text . la5tl ndexOf( ’ 55 ’) ; text . la5tlndexOf ( ’ 55 ’ te x t.la5t l ndexOf ( ’ 55 ’ 3) 6) // p 는 5 // p 는 2 // p 는 5 149 string.localeCompare(that) localCompare 메소드는 문자열을 매개변수 that 문자열과 비교합니다. 문자열 을 어떻게 비교하는지는 해당 환경의 로케일 정보에 따라 달라집니다. 문자열이 that 문자열보다 적은 경우에는 음수가 같으면 0이, 크면 양수가 반환됩니다. 이 는 array. sort 메소드의 비교 함수와 비 슷한 방법 입니다. var m ’ AAA ’ r ’ A ’ r ’ aa ’ I ’ a ’ m. sort(function (a , b) return a . localeCompare(b) ; }) f ’ Aa ’ I ’ aaa ’ ] ; r ’ aa ’ r ’ Aa ’ ·r // m은 (특정로케일에서’ a ’, ’ A’ r ’ aaa ’ r ’ AAA ’ ] string.match(regexp) match 메소드는 정규 표현식과 일치하는 부분을 문자열에서 찾습니다. 찾는 방 법은 g 플래그에 따라 달라지는데 g 플래그가 설정되지 않은 경우에 string.match Cregexp) 호출의 반환값은 regexp.exe cC string) 호출의 반환값과 같습니다. 그러 나 g 플래그가 설정 된 경우에는 일치하는 모든 부분을 배열로 반환합니다. 단, 캡 처 그룹과 일치하는 부분은 반환하지 않습니다. var text ’ <html><body bgcol or=l inen><p> ’ + ’ This is <b>bold<\/b>!<\/p><\/body><\/html> ’ ; VeryPDF Demo var tags /[^<>]+I<(\/?) ([A - Za - z ] +) ([^<>]*)>/g; var a , l ; a = te xt.match (tags ); for (i 0 ; i < a . le ngth ; i += 1) { document . writeln(( ’ // [ ’ + i + ’ ] ’ + a[i ]). entityify( // 결과 // 。。 뼈 15 0 [ 0 ] <html> )) ; // [1] <body bgco1or=linen> // [2] <p> / / [3] This i s / / [ 4] <b> // [5] bo1d // [6] </b> / / [7 ] / / [8 ] </p> // [9] </body> / / [10] </htm1> string.replace(searchValue, replaceValue} re place 메소드는 문자열을 대상으로 검색 및 대체 작업 을 실 행하여 새로운 문 자열을 생 성합니다. searc hValu e는 문자열이거나 정규 표현식 객체입니다. 만약 sear chValu e가 문자열 이면 첫 번째로 찾은 부분만이 교체됩니다. 그래서 다음 예 제의 결과는 실망스럽 게 도 m o the r-in law" 입니다. var resu1 t " mother in 1aw ". replace ( ’ ’ I ’- ’ ); searc hVa lu e 가 정규 표현 식이고 g 플래그가 설정된 경 우라면 일치하는 모든 부분 이 교체 됩 니다- 하지 만 정 규 표현식이라 하더라도 g 플래 그가 설 정되지 않은 경우 에 는 처음 한번만 교체 됩 니다. VeryPDF Demo r epl aceValu e는 문자열 이나 함수입니다. replaceValue가 문자열일 때, 문자 $는 특별한 의미 를 지 닙 니다. // 괄호 안의 3 개의 숫자 캡처 var oldareacode /\ ( (\d{ 3)}\) /g ; var p ’ (555 ) 666 -1 212 ’ . rep1ace(oldareacode , ’ $1 - ’ ) ; // p 는 ’ 555 - 666-1212 ’ 15 1 달러시펀스 교체되는내용 $$ $ $& 일치하는텍스트 $숫자 해당 숫자의 캡처 그룹 텍스트 $‘ 일치하는 부분 육때| 있는 텍스트 $’ 일치하는 부분 뒤에 있는 텍스트 replaceValue가 함수면 일치할 때마다 이 함수가 호출되고 이 함수가 반환하는 문 자열이 대체되는 텍스트로 사용됩니다. 이 함수에 전달되는 첫 번째 매개변수는 일 치되는 텍스트고, 두 번째 매개변수부터는 캡처 그룹에 캡처된 텍스트들입니다. String . method( ’ ent i tyify ’ function I var character ’ < ’ : ’ < ; ’, ’>’ ’ > ’ r ’ & ’ ’ &’ ’ " ; ’ I 1111 // replace 메소드를 호출한 결과를 반환하는 string . entityify // 메소드 반환. replaceVal ue 함수는 문자를 character 객체에서 찾아 // 그 결과를 반환 보통 이런 방법으로 객체를 사용하는 것 이 // switch 문을 사용하는 것보다 성능이 좋음, VeryPDF Demo return function ( return this.replace(/[<>& "] /g , function return character[c]; }) )( ·r )) ; alert( " <&> ". entityify( 。。 빼 152 ) ) ,. // < ; &> ; (c) string.search(regexp) search 메소드는 문자열 대신에 정규 표현식 객 체를 인수로 받는다는 것을 제외하 고는 indexOf 메소드와 같습니다 이 메소드는 일치하는 내용을 찾을 경우 첫 번째 일치하는 부분의 첫 번째 문자 위치를 반환합니다. 그리고 검색에 실 패했을 때는 -1 을 반환합니다.g 플래그는 무시되며 검색 시작 위치 를 지정하는 매개 변수는 없 습니다 var text var pos ’ and in it he says " Any damn foo 1 cou1d ’; text.searc h( /[ " ’ ]/) ; // pos 는 18 string.slice(start, end) slice 메 소드는 문자열의 일부분을 복사하여 새로운 문자열을 만듭니다. start 매개 변수가 음수이면 , 이 값에 문자열의 이며 기본값은 문자열의 .I e ngth .length 값을 더 합니다. end 매개변수는 옵션 값입니 다. 만약 end 매개 변수가 음수 이면 이 값에 문자열의 length 값이 더해집 니다 end 매 개변수의 기본값은 마지막 문자의 위치 + 1 입니다.p의 위치부터 n7~ 의 문자를 얻으려면 문자열 . s lice(p , p + n) 과 갚이 사 용하면 됩 니 다 문자열의 s ubstring 메소드와 배열의 .slice 메 소드도 참조하기 바 랍니다. var te x t ’ and in it he sa ys " Any damn foo1 cou1d ’; a text . s1i ce (18); // a 는 ”’ Any damn foo 1 cou1d ’ v ar b text . s1ice(O , 3 ) ; // b 는 ’ a nd ’ var c text . s1ice( - 5) ; VeryPDF Demo var // c 는 ’ cou1d ’ v ar d text . s1ice(19 , 32 ) ; // d 는 ’ Any damn foo 1 ’ 153 string.split(separator, limit) split 메소드는 구분자 C separator 매개변수)로 문자열을 쪼개어 각각의 항목이 담긴 배 열을 생성합니다. 옵션인 뻐lit는 나눌 개수를 지정합니다. separator 매개변수는 문자열 이나 정규 표현식 모두 가능합니다. 구분자로 빈 문자열을 사용하면 문자 하나 하나씩 나뒤어진 배열이 만들어집니다. var digits ’ 0 1 23 456789 ’; var a digits . sp l it( " , 5) ; // a 는 [ ’ 0 ’ r ’ l ’, ’ 2 ’ ’3’r I ’ 456789 ’ ] 구분자가 일반 문자열이면 문자열에서 구분자가 있는 곳을 모두 검색하게 되며, 구 분자 사이에 있는 텍스트들이 배열에 복사됩니다. 구분자로 정규 표현식 객체가 넘 어왔을 때 g 플래그는 무시됩니다 ’ 192 .1 68 . 1. 0 ’; i p . split ( ’ . ’ ) ; var lp var b // b 는 [ ’ 192 ’ I ’ 168 ’ r ’l ’r var c ’ lalb l c l ’ . split ( ’ // c 는 [ ' , ’a ’ I ’b ’ r ’c ’ var te xt VeryPDF Demo var d ’0’] | ’ ); ,'1 ’ last , first , middle ’ ; text.sp l i t (/\s* , \s* / ) ; // d는 [ // // // // 1 ’ l ast ’ ’ fir st ’ ’ middle ’ f f 구분자로 정규 표현식을 사용할 때는 주의해야 할 점이 있습니다. 그 중 하나는 캡 처 그룹에 캡처되는 텍스트도 결과에 포함된다는 것입 니다. 。。 빼 154 var e text . spl i t ( /\s* ( , )\s* /) ; // e 는 [ // // ’ last ’ I // ’ first ’ I // // // 1 ’ middle ’ 일부 환경에서는 구분자로 정규 표현식을 사용하면 결과 배 열에 빈 문자열이 포함 됩나다. var f ’ I a I b I c I ’ . split(/\I/) ; ’b ’ ’c ’ ] 어떤시 스 템에서 f 는 [ ' , ’a ’ ’b ’ , ’ c ’ // 어떤시 스템 에서 f 는 [ ’ a ’ // 다른 l 1 I " 1 string.substring(start, end) substring 메 소드는 음수로 된 매 개변수를 변환하지 않는 점을 빼면 와 같습니다 substring slice 메소드 메소드를 쓰는 것보디는 slice를 사용하는 것이 좋습니다. string.toLocaleLowerCase( ) VeryPDF toLocaleLowerCase Demo 메소드는 로케일 규칙을 사용하여 문자열을 소문자로 변환 한 새 로운 문자열을 반환합니 다. 이 메 소드로 이득을 보는 주된 언어 중 하나는 터 키어인데 , 왜냐하면 I를 i 대신 l 로 변환하기 때문입니다. string.toLocaleUpperCase( ) toLocaleUpperCase 메소드는 로케일 규칙을 사용하여 문자열을 대 문자로 변환 한 새 로운 문자열을 반환합니다. 이 메소드로 이득을 보는 주된 언어 중 하나는 터 키어 인데, 왜냐하면 i를 I 대 신 I 로 변환하기 때문입니다. 155 string.toLowerCase( ) toLowerCase는 문자열을 소문자로 변환하여 반환합니다. string.toUpperCase( ) toUpperCase 메 소드는 문자열을 대 문자로 변환하여 반환합니다 String .fromC 티ha 하rCode(char…) fromCharCode 메 소드는 인수로 넘어온 숫자값들을 문자열로 변환하여 반환합 니다. var a Str ing . fromCharCode // a 는 ’ Cat ’ VeryPDF Demo 。。 빼 15 6 (67 , 97 , 116 ); C ‘ H.A.P.T.E.R 入 ..-1 -- 드 ï 01 2.. 어 이없게 어리석은 작위 (style)를 줄줄 늘어놓는군! - ‘r쨌 .. 윌리얻 셰익스피어, 헨리 6서l 저'/1부 컴퓨터 프로그램은 인간이 만든 가장 복잡한 것 중에 하나입니다. 프로그램은 실질적으로 오류가 없어야 하는 수많은 함수, 문장, 표현식 둥으로 구성됩니다. 이러한 프로그램은 구현할 때 의도한 대로 동작하지 않 는 경우가 많으며 , 그 래서 보통 소프트웨어는 실질적인 사용기간 동안 계속해서 수 정 해야 합니다. 문제가 없는 프로그 램을 다른 정상적인 프로그램으로 변경하는 것 은 대단히 도전적인 일입 니다 프로그램은 VeryPDF좋은 Demo 미래에 수정할 여지가 있다는 것을 감안한(하지만 그에 따라 크 게 부담이 되지 않는) 구조를 갖습니다. 또한 좋은 프로그램은 명확한 프리젠테이 션을 갖습나다. 프로그램을 잘 표현하면, 이를 명확히 이해할 가능성이 높아지고 그로 인해 변경이나 오류 수정을 성공적으로 할 수 있습니다 이러한 개념은 모든 프로그래밍 언어에 해당하는 내용이며 특별히 자바스크립트 에는 더욱 그렇습니다. 자바스크립트의 느슨한 데이터 타입 체크와 과도한 오류 허 용은 컴파일 시에 프로그램 에 대한 품질을 보장하지 못합니다. 그러므로 이를 보완 하기 위해서는 엄격한 규칙을 정하고 코딩해야 합니다. 이 타 스 E 157 자바스크립트에는 좋은 프로그램을 만드는데 위험한 많은 수의 약점과 문제점이 있습니다. 자바스크립트에 있는 최악의 속성들은 반드시 피해야 합니다. 하지만 이 것뿐만 아니라 때때로 유용하지만 간간히 위험할 수 있는 속성들 또한 피해야 합 니다. 이러한 속성들은 유인성 불법 유해물 Cattractive nuisances) 이며 이러한 점 들을 피함으로써 다양한 유형의 잠재적인 오류를 피할 수 있습니다. 소프트웨어가 오랜 기간 동안 가치를 유지할 수 있는 직접적인 부분은 코드의 품 질입니다. 프로그램은 라이프타임 전체에 걸쳐서 수많은 손과 눈을 거칩니다. 프로 그램이 자신의 구조와 특성을 명확하게 나타낼 수 있으면, 머지 않은 장래에 수정 이 가해질 때 프로그램이 망가지는 일은 거의 없습니다 자바스크립트 코드는 때때로 일반에게 직접 전달이 됩니다. 그러므로 배포해도 문 제 없는 수준의 품질과 깔끔함을 항상 유지해야 합니다. 깔끔하고 일관된 프로그램 작성 스타일은 프로그램을 보다 읽기 쉽게 만듭니다. 프로그래머들은 좋은 스타일을 선정하기 위해서 끊임 없이 토의할 수 있습니다. 대 부분의 프로그래머는 자신이 현재 사용하고 있는 스타일에 단단히 고착해있습니 다. 이런 스타일은 보통 자신이 다녔던 학교나 첫 직장에서 유행하던 스타일입니 다. 일부 프로그래머는 프로그래밍 스타일에 전혀 관심이 없음에도 좋은 경력이 있 습니다. 이것을스타일이 별로중요하지 않다는증거로볼수 있을까요? 프로그래밍 스타일은 작문할 때 스타일이 중요한 것과 같은 이유로 중요하디는 것 이 밝혀졌습니다. 좋은 프로그래밍 스타일은 가독성을 높여줍니다. VeryPDF Demo 컴퓨터 프로그랩은 때때로 쓰기 전용 매체처럼 여겨지기 때문에 프로그램이 동작 하는 한 어떻게 작성했는지는 중요하게 여겨지지 않습니다. 하지만 프로그램이 동 작할 가능성은 가독성이 높을 때 놀랄 정도로 높아지는 것으로 밝혀졌으며, 그에 따라 의도한 대로 동작할 가능성도 높아진다는 것이 밝혀졌습니다. 또한 소프트웨 어가 실질적으로 사용되는 기간 내내 다양하게 수정되는 것은 소프트웨어의 본성 입니다. 프로그램을 잘 읽고 이해할 수 있다면, 이를 문제없이 수정하고 횡t상시킬 수 있다고 기대할 수 있습나다. 빼 15 8 n 3 필자는 이 책 전체에 걸쳐 일관된 스타일을 사용했습니다. 필자의 의도는 예제 코 드를 가능한 쉽게 읽을 수 있도록 하는 것이었습니다. 예제 프로그램의 의미를 이 해하는데 필요한 단서를 더 많이 제공하기 위해서 일관되게 공백 (whitespace) 을 사용했습니다. 블록이나 객체 리터럴의 내용은 4칸 들여쓰기를 했습니다. 그리고 κ와 ( 사이에는 빈 칸을 두어 K가 함수를 호출하는 것처럼 보이지 않게 했습니다 반드시 호출하는 경우에만 앞선 심볼과 (를 붙여서 작성했습니다.. (마침표)와 [를 제외한 중위 연산 자 앞뒤로는 빈칸을 붙였으며 모든 쉽표와 콜론 다음에는 빈칸을 붙였습니다. 필자는 가능하면 한 줄에 문장 하나를 위치시켰습니다. 한 줄에 여러 문장이 있는 경우 잘못 읽히는 경우가 있습니다. 만약 문장이 한 줄에 다 들어가지 않으면 , 쉽표 나 이항 연산자 다음에서 다음 줄로 나눴습니다. 이렇게 하는 것이 세미콜론 자동 삽입에 의해서 숨겨지는 오류를 줄여줍니다(세미콜론 자동 삽입에 대한 비극은 부 록 A에서 살펴봅니다) . 나뉘어진 나머지 문장은 4칸을 더 들여 쓰거나 모호한 경우 8칸을 들여 썼습니다(예를 들어 줄을 나눈 부분이 표문의 조건 부분인 경우) . 필자는 κ나 while 같은 구조적 문장을 사용할 때 블록을 사용합니다. 왜냐하면 다 음의 예처 럼 블록을 사용하지 않으면 오류가 발생하기 쉽습니다, i f (a ) b ( ); VeryPDF Demo 위의 코드가 아래와 같이 됐을 때, if (a ) b ( ); c( ); 이 타 스 E 159 이 코드는다음과같이 인식되어 오류를찾기 힘들수 있습니다. if (a ) { b ( ); c ( ); 하지만 실제 위의 코드가 의미하는 바는 다음과 같습니다. if (a) { b ( c( ); ); 이런 돗인 것처럼 보이는데 실제로는 다른 돗을 의미히는 코드는 버그의 원인이 되기 쉽습니다 중괄호 한 쌍은 찾기 어려운 버그를 막는 저렴한 예방책 중에 하나 입니다. 필자는 항상 K&R 스타일을 사용합니다. 즉 {를 줄의 처음에 놓는 것이 아니라 마지 막에 놓습니다. 이렇게 함으로써 자바스크립트의 r eturn 문과 관련된 치명적인 설 계 실수로 인한문제를 피할수 있습니다. 필자는 예제에 VeryPDF Demo 얼마의 주석을 포함시켰습니다. 후에 프로그램을 읽게 되는 사람 (또는 자신)에게 어떤 생각으로 이렇게 작성했는지 알게 해주는 주석을 남기는 것 을 좋아합니다. 때때로 주석을 미래의 자신에게 중요한 메시지를 보내는 타임머신 이라고생각합니다. 또한 주석을 항상 최신 내용에 맞게 업데이트 하려고 노력합니다. 잘못된 주석은 오히려 프로그램을 더 읽기 어렵고 이해하기 힘들게 만듭니다. 이런 상황은 정말 안좋습니다. 뼈 mo Q J 필자는 다음의 예처럼 불필요한 주석으로 여러분의 시간을 빼앗지 않으려고 노력 했습니다. i =O ; //i 를 0 으로설정 자바스크립트에서 필자는 한 줄 주석을 선호합니다. 블록 주석은 공식적인 문서화 나 일시적으로 코드를 주석화시 킬 때 (comment out) 만 사용합니다. 필자가 선호하는 또 하나는 주석 없이도 프로그램 자체가 모든 것을 말하는 구조 를 갖는 것입 니다. 항상 성공적인 것은 아니지만 그렇 게 하려고 노력 하고 있으며 그렇지 못 한 경우에 는 주석 을 사용합니다. 자바스크 립 트는 C 구문을 가지고 있지만, 블록은 유효범위를 갖지 않습니다 그래 서 변수를 처 음 사용하기 바로 전에 선언하라는 권고는 자바스크립트에서는 나쁜 충고입니다. 자바스크렵트는 블록 유효범위가 아니라 함수 유효범위가 있습나다. 그 래 서 필자는 모든 변수를 함수의 첫 부분에서 선언합니다. 자바스크립트는 변수 가사용된 후에 선언되는 것 을 허용하기는 하지만, 필자는 이렇게 실수처 럼 보이는 프로그래밍을 원하지 않습니다 실제 실수라면 눈에 바로 될 수 있어야 합니다. 이 와 유사하게 필자는 할당 표현식을 표 문의 조건 부분에 결코 사용하지 않습니다- if (a b) { . . . } VeryPDF Demo 왜냐하면 위의 예 는 마치 아래와 같은 코드가 원래 맞는 데 실수를 한 것처럼 보이 기 때 문입 니다. if (a b) { ‘ . . } 이근 타 스 161 필자는 이렇게 실제 실수가 아닌데 실수처럼 보이는 코드를 가능한 피하려고 합 니다. 필자는 switch 문의 고 다음 case case에서 하나의 절로 내려가게 (f에1 case through) 절을 실행한 후 벗어나지 (break 문) 않 하지 않습니다. 전에 다음 case 절까지 실행시키는 것이 때때로 좋은 이유에 관해 강력한 연설을 한 후에, 필자가 작성한 코드에서 이로 인해 발생한 의도하지 않은 버그를 찾게 됐습니다. 이러한 경험을 통해 다음 case 절까지 실행하는 것이 나쁘다는 것을 배우게 된 것은 어쩌면 행운 이었습니다. 왜냐하면 이후로 언어의 기능들을 살펴볼 때 때때로 유용하지만 어떤 경우에는 위험한 기능들에 특별한 주의를 기울이기 때문입니다. 이러한 것들은 제 대로 사용됐는지 알기가 어렵기 때문에 가장 안 좋은 부분이라고 할 수 있습니다. 이런 부분들이 버그가숨어있는부분입니다. 품질이라는 문제는 자바스크립트의 설계나 구현, 표준화 단계에서 중요하게 고려 된 내용이 아니었습니다. 이런 점이 언어의 약점들을 피해서 사용하려는 사람들에 게 커다란 짐을 안겨줬습니다 자바스크립트는 규모가 큰 프로그램에 필요한 것들을 제공하지만 반면에 대규모 프로그램에 반하는 것들도 제공합니다. 예를 들어 , 전역변수를 쉽게 사용할 수 있 는 편리함을 제공하기는 하지만 프로그램의 복잡함이 커지면 커질수록 전역변수 는문제 발생 확률을높입니다. 필자는 애플리케이션이나 라이브러리를 포함하는 하나의 전역변수를 사용합니다. VeryPDF Demo 모든 객체는 자신의 이름 공간 (namespace) 을 갖기 때문에 이렇게 하는 것이 객체 를 사용하는 코드를 구성하는 쉬운 방법입니다. 클로저의 사용은 더 나은 정보은닉 과모률화를강력하게 합나다. ? 때 / m ‘ Q 4 、 醫혔 ./ / / , / A. P.T. E. R).(꾀 아릎다순 속λj ò~l 대싼 만λi 나는 대답을 기다리며 내 손을 그대의 발에다, 내 눈을 그대의 상이象) 에다, 내 심장을 그대의 전신 각부에다 감히 더럽히기를 꺼리지 않겠 소. 그대를 위하여 근연 극기 하는 -윌리얻 셰익스피어, 사랑의 헛수고 양휠’ .. 필자는 작년에 컴퓨터 프로그램에서 말 그대로 아름다움을 주제 로 한 모음집인 IFBeautiful Code .!J (한빛미 디어 , 2007) 의 한 장 (chapte r ) 을 위한 기고가로 초대받았는 데, 그 장을 자바스크립트로 작성하고 싶었 습니다. 자바스크 립트라는 언어가 기반하고 있는 추상적 이고 강력하면서도 유용한 것들을 보여주길 원했습니다 그리고 자바스크립트가 판에 박힌 역할을 하는 곳을 연상시키 는 브라우저나 그 외 다른 환경들을 피하고 싶었습니다. 자바스크립트에 무게 를 실 어 주는 뭔가 훌륭한 것을 보여주고 싶었습니다. VeryPDF Demo 필자는 즉시 JSLint(부록 C 참조)에서 사용한 Vaughn Pr att의 하향식 (top down) 연산자 우선 순위 파서를 염두에 두었습니다 파싱은 컴퓨터 작업 중에서 중요한 주제 중 하나입니다. 언어 자체를 위한 컴파일러를 작성할 수 있는 능 력의 여부가 여전히 한 언어의 완전성을 테 스트하는 잣대입니다 필자는 자바스크립트로 작성한 자바스크 립 트 파서의 모든 코드를 책 에 싣고 싶었 습니 다. 하지 만 필자의 장(chap ter ) 은 30 , 40개의 장 중에서 단지 하나일 뿐이 었 습니다 그 래서 사용해야 할 페이지 수에 제한을 생각하지 않을 수 없었으며 , 셜상 아름다운 혐에 대한 단상 | 16 3 가상으로 그 책을 읽게 되는 대부분의 독자는 자바스크립트에 대한 경험이 없어서 자바스크립트 언어 자체와 특징들도 설명을 해야만 하는 상황이었습니다. 그래서 언어의 부분집합을 만들기로 결정했습니다. 이렇게 함으로써, 언어 전체를 파싱할 필요도 없어졌고 언어 전체에 대해 기술할 필요도 없어졌습니다. 필자는 자바스크립트의 부분집합을 단순화된 (Simplified) 자바스크립트로 불렀습니다 파 서를 작성하는데 필요한 기능들만 부분집합에 포함시켰기 때문에 부분집합을 구 성동}는 것은 쉬웠습니다. 이렇게 해서 If'Beautiful Code.!J의 한 장을 집필할 수 있 었습니다. 단순화된 자바스크립트에는 다음과 같은 좋은 것들만이 포함돼 있습니다. 일급 객체 (first-class objec야인 함수1 단순화된 자바스크립트에서 함수는 어휘적 유효범위를 갖는 람다 (lambda) 입 니 다 프로토타입으로 상속을 하는 동적 객체 객체는 클래스가 필요 없습니다. 어떤 객체든지 단순히 할당하는 식으로 새로운 구성요소를 추가할 수 있습니다. 객체는 다른 객체로부터 상속 받을수있습니다. 객체 리터럴과 배열 리터럴 새로운 객체와 배열을 생성하는 매우 편리한 표기법입니다. 자바스크립 VeryPDF Demo 트의 리터럴은 ]SON이라는 데이터 교환형식에 영감을주었습니다 이 부분집합은 좋은 점 (Good Parts) 중에서도 가장 좋은 부분들만을 포함하고 있 습니다. 매우 작은 언어이기는 하지만 매우 표현적이며 강력합니다. 자바스크립트 에는 실제로 별로 득 될게 없는 많은 수의 부가 기능이 있습니다. 그리고 이어지는 부록들에서 살펴보겠지만 오히려 손해가 되는 기능도 많이 있습니다 하지만 이 부 분집합에는 그러한 나쁜 것들이 모두 제외되어 하나도 포함돼 있지 않습니다. 1 역자 주/ 일급 객체에 대한 설명은 1 장의 역자 주를 참고하세요 r L 뼈 16 4 m 단순화된 자바스크 립 트는 아주 엄격한 의미에서 자바스크립 트의 부분집합은 아닙 니다. 왜냐하면 필자가 몇몇 속성을 추가했기 때문입니다. 여기에는 pí가 간단한 상 수로 추가돼 있는데 , 이 렇 게 한 것은 파서의 기능을 보여주기 위해서였습니다. 또 한 단순화된 자바스크립트에는 더 나은 예약어 정책을 보이려고 했으며 심지어 예 약어가 필요 없다는 접도 나타냈습니다. 그래서 함수에서는 어떤 단어든지 변수 (또는 매개변수)나 속성(이를테면 표 둥)의 이름으로 쓰일 수 있지만 동시에 둘 다 에 쓰일 수는 없습니다. 이렇게 정의하면 예약어라는 개념이 없기 때문에 사용해서 는 안 되는 속성들을 모두 알고 있을 필요가 없어져서 언어 를 배우기가 훨씬 쉽 습 니다. 또한 새 로운 기능을 추가하기 위해 더 많은 단어를 예약할 필요가 없어지므 로 언어 를 확장하는 것도 보다 쉬워집니다 필지는 또한 블록 유효범위를 추가했습니다. 블록 유효범위가 꼭 필요한 기 능은 아 니지만 없을 경우에는 이 개념에 익숙한 프로그래머들에게 혼란을 줍니다. 필자가 블록 유효범위 개념 을 추가한 주된 이유는 이 파서가 자바스크 립트 외에 블록 유 효범 위 개념을 잘 갖춘 다른 언어를 파싱하는데에도 사용할 수 있겠다는 생각 때 문이었습니다. 필자가작성한파서의 코드는블록유효범위를사용할수 있든지 없 든지 간에 그것에 영향을 받지 않는 스타일로 작성되었습니다 필자는 여러분이 이 런 식으로 프로그 래멍하기 를 권합니다. 필자가 이 책 을 구상하기 시 작했을 때 원했던 것은 부분집합 개념을 더 발전시키 고, 기 존의 언어에 변화를 주지 않으면서 중요성이 떨어지는 기능들을 배제시키고 VeryPDF사용하는 Demo 방법 을 보이 는 것이었습니다 각 기 능의 비 용이 제대 로 계산되지 않은 체 기능 중심으로만 설계된 제품을 많이 볼 수 있숨니다 제품을 이해하고 사용하기 어렵게 만드는 기능은 소비자에게 오히 려 부정적인 요소입 니다 사람들 이 좋아하는 제품은 딱 펼요한 기 능을 하는 제품입 니다. 제대로 된 기 능을 하는 제품을 설 계하는 것이 기능만 많은 제품을 설계 하는 것보다 훨씬 더 어렵 습니다. 아름[댄 속성에 대한 단상 | 16 5 기능을 추가하기 위해서는 명세를 정하고 설계하고 개발하는 비용이 필요합니다. 거기에다가 테스트 비용까지도 포함됩니다. 기능이 많으면 많을수록 문제를 일으 키거나 또는 다른 부분과 이상하게 상호작용할 기능이 많아질 가능성이 높아집니 다. 소프트웨어 시스템에서 저장 비용은 이제 거의 무시해도 될 문제가 됐지만 모 바일 애플리케이션에서는 여전히 중요한 문제입니다 또한 무어의 법칙이 배터리 에는 적용되지 않기 때문에 실행 비용의 상승도 무시 못할 문제입니다. 기능의 추가는 문서화 비용도 관련돼 있습니다 모든 기능은 매뉴얼에 페이지를 가 중시키고 이를 익히기 위한 비용도 증가시컵니다. 소수의 사용자에게만 가치를 제 공하는 기능들은 그 외 대다수의 사용자에게 불필요한 비용 추가라는 짐을 지우게 됩니다. 그러므로 제품이나 프로그래밍 언어를 설계할 때는 제대로 된 핵심 기능 들, 즉 좋은 점만을 포함해야 합니다. 이런 기능들만으로도 필요한 것을 대부분 할 수있습니다. 우리는 사용하는 제품들에서 좋은 접 (good parts) 만을 찾아낼 수 있습니다 단순 함이야말로 가치가 있으며 만약 단순하게 제공되지 않는다면 우리가 직접 단순화 할 수 있습니다. 필자의 전자레인지는 정말 많은 기능들이 있습니다. 하지만 필자 가 사용하는 기능은 단순히 시계와 조리 기능뿐입니다. 그런데 시계의 경우는 시간 을 맞추는 일조차도 도전적입니다. 우리는 좋은 점만을 찾고 이것들만 사용함으로 써 기능 위주 설계로 인한 복잡함에 대처할 수 있습니다. 제품이든지 프로그래밍 언어이든지 간에 좋은 점 (good parts) 으로만 설계된다면 VeryPDF좋을것입니다. Demo 뼈 「」 @ m 짧쫓 、 I'X:"'I페 나쁘지만 사흥해。 F 농}는 부분들 (AwfUl part S) 언행이 모두 귀감(awful)이 되는 - - 윌리엄 셰익스피어, 페리클리스 람했? -- 이번 장에서 는 자바스크립트에서 쉽게 피하기 힘든 문제가 있는 부분들을 살펴볼 것입 니다. 이러한 부분들을 잘 인지하고 적절히 다룰 준비를 해야 합니다. 01 I 전역변수 VeryPDF자바스크립트의 Demo 나쁜 점들 중에서 가장 나쁜 점은 언어가 전역변수에 기반하고 있 다는 것입 니다 전역 변수는 모든 유효범위 (scope) 에서 보이는 변수입니다. 매우 작은 프로그램 에서 는 전역변수가 편리할 수 있지만, 프로그램이 점점 커짐에 따라 전역변수는 다루기가 까다로워집니다. 전역변수는 언제든지 프로그램의 모든 부분 에서 변경될 수 있기 때문에 프로그 랩의 동작을 심각할 정도로 뒤엉키게 할 수 있 습니다. 그러므로 전역변수를 사용하면 프로그램의 신뢰성을 저하시컵니다. 전역변수는 같은 프로그 램 내에 있는 하위 프로그램이 독립적으로 실행되는 것을 더 어 렵 게 만듭니다 하위 프로그램들이 같은 이름의 전역변수들을 공유하면, 각각 s히)꺼I 나백뺀보 지l멘싼 x 만λ 사샘}뽕용응해에뺨뺨빼 빠附빼。야염얘 HO f야벼융하}뿐들(뼈뼈빼l내P 띠벼때떼떼 따짜때。야 때 m 떠 rt꽉 ts | 16 7 서로를 방해하고 오류가 발생하기 쉽습니다. 게다가 오류가 발생했을 경우 어디가 잘못됐는지 찾기가어려워집니다 많은 언어에 전역변수가 있습니다. 예를 들어, 자바의 public static 속성은 전역변 수입니다. 전역변수가 자바스크립트에서 유독 문제가 되는 것은 전역변수가 필요 한 경우에만 사용할 수 없기 때문입니다. 자바스크립트는 링커가 없습니다. 그래서 모든 컴파일 단위는 하나의 공용 전역객체에 로딩됩니다. 전역변수를 정의하는 방법은 세가지가 있습니다. 첫 번째 는 어떠한 함수에도 속하 지 않는위치에 다음과같이 var 문을 사용하는 것 입니다. var foo va l ue ; 두 번째 방법은 전역객체에 직접적으로 속성을 추가하는 것입니다. 전역객체는 모 든 전역변수의 컨테이너입니다. 웹 브라우저에서 전역객체 이름은 window입니다. window.foo value ; 세 번째 방법은 변수를 선언 없이 사용하는 것입니다. 다음과 같은 방법이 묵시적 인 전역변수선언 방법입니다 VeryPDF Demo foo value ; 이런 방법은 초보자들이 변수를 선언하지 않아도 사용할 수 있게 하기 위해서 고 안된 것입니다. 하지만 불행히도 이렇게 선언 없이 변수를 사용하는 것은 많은 실 수를 유발합니다. 자바스크립트의 이러한 정책은 때때로 매우 찾기 힘든 버그를 만 들기도합니다. 1‘ 역자 주/ 즉 var 없이 변수를 바로 사용하는 것입니다 부언하면 함수 내에서건 블록 내에서건 var로 선언한 적이 없는 변 뼈 수를 사용하연 그 변수는 전역변수가 될니다 168 A I 유효범 위 (Scope) 02 자바스크립트의 구문은 C 에서 가져온 것입니다.C 같은 구문을 가진 다른 언어 들 은 블록(중괄호로 묶인 문장들의 집합)이 유효범위를 가집니다. 블록 내에서 선언 된 변수들은 블록 바깥에서 보이지 않습니다. 자바스크립트는 블록 구문을 사용하 기는 하지만, 블록 유효범위를 제공하지 않습니다. 즉 블록 내에서 선언한 변수는 블록을 포함하는 함수 내부 모든 곳에서 볼 수 있습니다. 이러한 속성은 다른 언어 에 익숙한 프로그래머들에게 는 놀랄만한 일입니다 대부분의 언어에서는 일반적으로 변수가 처음 사용되는 지점에서 선언하는 것 이 가장 좋습니다 하지만 자바스크립트에서는 블록 유효범위를 갖지 않기 때문에 이 렇게 하는 것이 좋지 않습니다. 대신에 함수에서 사용하는 모든 변수를 함수의 첫 부분에서 선언하는 것이 좋습니다. 03 I 세미콜론삽입 자바스크 립트에 는 자동으로 세미콜론을 삽입하여 잘못된 프로그램을 교정하려는 메커니 즘이 있습니다 하지만 이러한 메커니즘에 의존해서는 안 됩 니다. 그렇게 하 면 더 중 대한 오류가 발생할 수 있습니다. 때때 로 세미 콜론 이 원하지 않는 곳에 자동 삽입됩니다 다음의 예를 통해 세미콜론 VeryPDF 이Demo r e turn 문장에 자동 삽입됐을 때의 결과를 살펴보겠습니다. return 문으로 값을 반환하려면 , 값을 나타내는 표현식의 시작이 반드시 return과 같은 줄에 있어야 합 니다. return stat u s : true 나쁘지만 사용해야 하는 뿐들(뼈1 parts) I 16 9 이 예는 status 라는 속성을 가진 객체를 반환하려는 것 같이 보입니다. 하지만 안 타깝게도 세미콜론의 자동 삽입으로 인해 undefine d를 반환합니다. 프로그램을 잘못 해석하게 하는 세미콜론 자동 삽입에 대한 아무런 경고도 없습니다. 이 문제 를 피하기 위해서는 다음과 같이 {를 다음 줄의 시작이 아니라 re turn 이 있는 줄의 마지막에 두어야합니다 return { status : true 04 I 여l 약어 다음에 나오는 단어들은 모두 예약어입니다. abs t ract boo l ean conti nue b reak byte debugge r default export e x tends f a lse fina l imp l eme n ts new n u ll import p ackag e in case finall y float instanc e of private catch char d elete i nt do clas s d ouble e lse const enum for functio n go to if i n terface pro t ected public long return native short static super switch synchronized this throw throws t r ansient true t r y typeof v ar v olati l e vo id wh i le wi th VeryPDF Demo 이 단어들의 대부분은 실제 자바스크립트에서 사용하지 않습니다. 이 예약어들은 변수나 매개변수의 이름으로 사용할 수 없습니다- 예약어가 객체 리 터럴에서 속성 이름으로사용될 때는따옴표로묶어줘야합니다. 이렇게 사용된 이 름은 마침표 u 표기법으로는 사용할 수 없고, 대신에 대괄호 표기법으로 사용해야 합니다. 뼈 A 17 0 var method; / / var class ; / / 잘못된 사 용 。 bject {box : value} ; // 。 bject {case : v alue} ; // 잘못된 시용 。 bject ’ case ’ 。 bject .bo x 。 bject . case 。 bject[ ’ case ’ 05 I value} ; value ; value ; value ; 0 0 1< 1< // 0 1< // 0 // 잘못된 사용 // 0 1< 1< 유니코드 자바스크립트는 유니 코드가 최대 6 5 ,5 36자를 갖는 시 절 에 설 계됐습니다. 하지만 유니 코드는 현재 백만 자 이 상을 수용할 수 있습니다 자바스크 립트에서 문자는 1 6 비 트 입니다. 이것 은 원래 유니코드 65 ,5 36자(현재 BMP(Basic M ultilin gual Pl ane) 로 불려짐 )를 다루는 데 는 충분합니다. 여기에 포 함되지 않는 유니코드 문자들은 문자의 쌍으로 표현할 수 있습니다 즉 \u 표기 두 개 를 연속으로 붙여서 사용합니다 2 유니코드 상으로는 이 렇 게 16비트 글자 한 쌍 (pa ir ) 이 한 글자입 니다 하지만자바스크립트는 이러 한한쌍을두 개의 글자로생 각합니다. VeryPDF 06 Demo I typeof typeof 연산자는 피연산자의 타입을 알 수 있게 해 주는 문자열을 반환합니다. 그 래서 다음의 예 는 ‘ num b e l ’ 를 반환합니다. typeof 98 . 6 2. 역자 주/ 예를 들어 높은음자리표를 나타내는 lJ+1D11E는 ₩uD없4₩uDD1E과 같이 나타냄니다 이러한 묘기를 pal r라고 하며 자바에서도 사용하는 방법입니다 더 자세한 내용은 surrogate http://en.wikipedia αg/wiki/Surrogate_pair를 잠조하 세요 나보지만 λ용해야 하는 뿐들빼ul parts) I 17 1 그러나 안타깝게도 다음의 예는 null 이 아니라 obj ec t를 반환합니다. typeo f nu ll 그러므로 null을 확인하는 더 좋은 방법은 다읍과 같이 하는 것입니다. my value nul l 여기에서 더 큰 문제는 객체인지 아닌지를 판별할 때입니다. typeof 연산자는 null 과 객체를 구분하지 못합니다. 하지만 null은 거짓이고 모든 객체는 참이라는 속성 을 이용하면 다음과 같이 구분할 수 있습니다. if (my va l ue && typeof my value // my 뒤에 나오는 ’ 。 bject ’ ) { value 는 객체 나 배 열 10. NaN 절과 11. 가짜 배열 (Phony Ar rays) 절도 참조하기 바랍니다 정규 표현식 객체에 대한 타입 값은 자바스크립트 실행환경에 따라 다르게 나타납 니다. 다음의 예를 어떤 실행환경에서는 ‘objec t’라고 반환하는데 반해 어떤 환경 에서는 ‘function’ 이라고 VeryPDF Demo 반환합니다. ‘ regexp ’ 를 반환동}는 것이 더 유용해 보이기 는 하지만 표준에서는 이를 허용하고 있지 않습니다. typeof /a/ 뼈 A 172 07 I parseInt parseInt는 문자열을 정수로 바꿔주는 함수입니다. 이 함수는 문자열의 첫 문자 부터 변환을 하다가 숫자가 아닌 문자를 만나게 되면 변환을 멈줍니다 그래서 pars elnt(“ 16") 과 parselnt(“ 16 tons ") 은 결과가 같습니다. 변환되지 않은 여분의 텍스트가 무엇인지 알려주변 좋겠지만 이 함수는 그렇 게 하지 않습니다. 문자열의 첫 번째 문자가 0이면 문자열은 1 0진수 대신에 8진수로 간주됩니다.8진 수에서 8과 9는 숫자가 아니기 때문에 parselnt ("08") 과 pars elnt(" 09 ") 의 결과값 은 0 입니다. 이러 한 오류는 날짜나 시간을 파싱할 때 문제를 일으킬 수 있습니다. 그나마 다행인 것은 parselnt에 기수(진법)를 지정할 수 있다는 것입 니다. 그래서 parselnt( “ 08" , 10) 의 값은 8 입니다 parselnt를 사용할 때 는 항상 기수 매개 변수를 지정할것을권합니다, 08 I + + 연산자는 덧셈 을 하거나 문자열을 연결합니다. 어떤 작업을 할지는 피연산자의 데이터 타입에 따라 결정됩 니다. 둘 중에 하나의 피연산자가 빈 문자열이면, 다른 피연산자를 문자열로 변환하여 결과값을 돌려줍니다. 두 피연산자가 모두 숫자이 면 덧셈을 실행합니다 이 외의 경우에는 두 피연산자를 모두 문자열로 변환하여 문자열을 VeryPDF 두 Demo 연 결합니다 이러한 복잡한 행동이 버그의 일반적인 원인이 됩니다+ 연산자를 더하기 로 사용한다면 두 피연산자가 모두 숫자인지 확인하는 것이 좋습 니다‘ 나쁘지만 λ냉해야 핸 쁨들뼈1 parts) I 173 I 부동소수점 09 이진 부동 소수점 (binary floating - p oint) 숫자는 소수 부분을 제대로 처리하지 못합니다. 그래서 0 .1 + 0.2는 0 . 3과 같아야 하지만 실제로 그렇지 않습니다. 이러 한 문제는 자바스크립트에서 가장 빈번하게 보고되는 버그이며 이진 부동 소수점 연산에 관한 IEEE 표준 (IEEE 754) 을 채택한 고의적인 결과라고 볼 수 있습니다. 이 표준은 많은 애플리케이션에 자주 채택되지만 중학교만 가도 배울 수 있는 당 연한 규칙을 위반하고 있습니다 다행히도 부동 소수점에서 정수 부분에 대한 연 산은 정확합니다. 그래서 소수점 부분의 연산 오류는 값을 조정함으로써 피할 수 있습니다. 예를 들어 센트까지 포함하는 달러 값은 여기에 100을 곱한 후에 덧셈을 합니다 그리고 나서 이 결과를 다시 100으로 나누어서 원하는 결과를 정확히 얻을 수 있 습니다. 사람들은 보통 돈을 계산할 때 그 결과가 정확할 것이라고 당연하게 생각 합니다 그러므로 돈과 관련된 계산이라면 이 문제와 관련해서 더욱 주의를 기울여 야합니다 10 I NaN NaN은 IEEE 754에 정의돼 있는 특별한 값입니다. N aN은 숫자가 아님 (no t a number) 을 의미함에도 다음의 예는 참입 니다. VeryPDF Demo typeo f NaN ’ nu mber ’ 11 참 이 값은 문자열이 숫자 형태가 아닌 데 이 문자열을 숫자로 변경하려 하는 경우에 발생합니다. 예를 들면 다음과 같습니다. + ’0’ 174 ’ 。 op s ’ 뼈 + A 11 0 11 NaN NaN 이 산술 연산의 피연산자이면 결과는 NaN 이 됩니다. 그러므로 일련의 산술 공 식을 실행한 결과가 NaN 이라면 적 어도 피연산자 하나가 NaN이거나 어느 부분에 선가 NaN이 발생했다는 뜻입니다 앞서 살펴본 것처 럼 typeof 연산자는 숫자와 NaN을 구분하지 못합니다. 그리고 놀 랍게도 다음의 예가 보여주는 것처럼 NaN은 자신과 같지 않습니다. NaN NaN NaN ! == NaN // // 거짓 참 자바스크 립트는 숫자와 NaN을 구분하도록 isNaN이라는 함수를 제공합니다. isNaN (NaN) // 참 isNa N(O) // 거 짓 isNaN ( ’ oops ’ ) // 참 isNaN ( ’ 0 ’ ) // 거짓 isFinite 함수는 NaN과 Infinity를 거부하기 때문에 어떤 값이 사용할 수 있는 숫 자인 지를 확인하는데는 isFinite 함수가 최상의 방법입니다. 한가지 아쉬운 점은 isFinite 는 인수로 넘어온 값을 숫자로 변환하려고 합니다 그래서 값이 실제 숫자 가 아닌 경우에는 적절하지 않습니다. 그러므로 다음과 같이 isNumber 함수를 정 VeryPDF의해서 Demo사용하는 것도 좋은 방법입니다. var isNumber function isNumber(value ) return typeof value ’ number ’ && isFinite(value); 나보지만 人탱해야 핸 쁨들(빼1 part히 | 175 11 1가짜 배열 (Phony Arrays) 자바스크립트는 진정한 배열이 없습니다. 하지만 그렇다고 해도 전부 나쁘지는 않 습니다. 자바스크립트의 배열은 실제 사용하기 쉽습니다. 굳이 크기를 지정하지 않 아도 되고, 결코 첨자 경계를 초과했다는 오류를 발생하지 않습니다 하지만 성능 에 있어서는 진짜 배열보다 꽤 나뽑니다. typeof 연산자는 배열과 객체를 구분하지 않습니다. 그러므로 값이 배열인지 확인 하기 위해서는 con s truc to r 속성을 확인해봐야 합니다. if (my_value && typeof my_value my value . constructor // my ' obj ect ’ && Array ) value 는 배열 이 확인 방법은 배열이 다른 프레임이나 창 (window) 에서 만들어진 경우 제대로 동작하지 않습니다. 그래서 다음과 같이 수정해야 그러한 경우에도 잘 확인할 수 있습니다. if (m y value && typeof my value VeryPDF Demo ’ 。 b j ect ’ && typeof my value .l engt h ’ number ’ && (my value . property IsEn umerable ( ’ length ’ )) // my value 는 배열 { ar guments 배열은 배열이 아닙니다. arguments는 le ngth 속성을 가진 객체입니 다. 위의 확인 방법을 사용하여 arguments 배열 을 테스트하면 배열로 구분하는데 이는 arguments가 배열 메 소드들을 가지고 있지 않더라도 때때로 적절할 수 있습 니다. 이 확인 방법의 한 가지 문제점은 prope rtyIsEnumerable 메소드가 재정의 되는 경우 제 대 로 동작하지 않는다는 것입니다 뼈 17 6 A 12 I 거짓인 값들(Falsy Values) 자바스크립트는 [표 A - l]에 나오는 것처럼 놀라울 정도로 많은 거짓 값이 있습 니다. 〔표 A- 1J 자바스크립트의 많은 거 짓 값 값 데이터타입 O 숫자 NaN(숫자가아님) 숫자 " (빈문자열) 문자열 false 불리언 null 객체 undefined undefined 이 값들은 모두 거짓이지만, 서로 맞바꿀 수 없습니다. 예를 들어 어떤 객체가 특정 속성 이 있는지 확인하는 다음과 같은 코드는 잘못된 방법 입 니 다. v alue if myObject[name ] ; (value null ) alert (n a me + ’ not found . ’ ) ; 체 에 없는 VeryPDF객Demo 속성 을 참조하면 값은 undefined 입 니다. 그런데 코드에서는 이 를 n ull 과 비 교하고 있습니다 비교를 위해 보다 신뢰 있는 연산자 대신에 연산자 (부록 B 참조) 를 사용하고 있는 데 이 연산자는 필요한 경우 타입을 변환하여 비 교 하기 도 합니다 이러한 두 가지 문제로 이 코드는 제대로 동작할 수도 있고 안 할 수도 있습니다. 즉 m yObj ec t[namel 이 실제 존재하지 않는 경우에는 문제 없 이 동작하지만, myObject[namel 이 존재하는 데 그 값이 뻐인 경우에 는 제 대 로 동 작하지 않습니다 그러므로 위의 값들이 모두 거짓 이 라 해도 서로 바꿔가며 써서는 안 되 고경우에 맞는 값을 사용해야합니 다. 나쁘지만 사용해야 하는 쁨들뼈ul parts) I 177 undefine d와 N값이은 상수가 아닙니다. 이 둘은 전역변수이며 원승}는 경우 값을 변 경할 수도 있습니다. 실제로 이것은 불가능해야 맞는데 가능한 게 현실입니다. 그 렇다 하더라도 절대 undefine d와 N aN의 값을 변경해서는 안 됩니다. 13 I hasOwnProperty 3장에서 hasOwnProperty 메소드는 for in 문의 문제를 해결하기 위한 대안으로 필터 역할을 했습니다. 불행히도 hasOwnProperty는 연산자가 아니라 메 소드여 서, 이 메소드를 다른 함수나 심지어는 함수가 아닌 값으로 대체할 수 있습니다. var name ; another stooge.hasOwnProperty for null; if (another stooge . hasOwnProperty (n ame)) document.writeln(name + ’: 14 // 문제가되는지점 (name in another stooge) { // 문제 발생 ’ + another_stooge[name]) ; I 객체 자바스크립트의 객체는 프로토타입 체인 상의 구성요소들을 불러올 수 있기 때문 VeryPDF Demo 에 결코 온전히 빈 상태를 가질 수 없습니다. 그런데 때때 로 이 점이 문제가 될 수 있습니다. 예를 들어 텍스트에서 각각의 단어가 몇 번 나오는지 숫자를 세는 프로 그램을 작성 한다고 가정해 보겠습니다 먼저 스트를 소문자로 통일시키고 난 후, split toLowerCase 메 소드를 사용하여 텍 함수를 정규 표현식과 함께 사용하여 각 각의 단어를 배열에 담을 수 있습니다. 그리고 나서, 배열을 돌면서 각각이 몇 번 나오는지 숫자를 셀 수 있습니다 따 뼈 17 8 X A var l ; var word ; var te x t " This oracle o f comfort has so plea sed me , " + " That when 1 am in heaven 1 shall desire " + " To see what this child does , " + " and praise my Cons truc tor ."; var words text . toLowerCase( ) . split(/[\s , . ] +/) ; var count {} ; for ( i 0 ; i < words . length ; i += 1) word if words[i] ; (count [wo rd] ) count[ word] } else { += 1 ; count [word] 1; 예제의 결 과를 살펴 보면 count[ ‘ this ’ ]는 2고 co unt . heave n은 1 입니다. 하지만 coun t. co n s tru c to r는 이상하게 보이는 문자열을 포함하고 있습니다. 이런 이유는 count 객 체가 co u s tru c to I 라는 객체를 속성으로 갖는 O bjec t. pro totype을 상속 받았기 때 문입니다 + 연산자처럼 += 연산자는 피연산자가 숫자가 아닌 경우 더하 지 않고 연 결을 합나다. 그 러 므로 count[ ‘ c o n s tructo r ’ J += 1 차례가 왔을 때 += 는 객체 인 co unt [ ‘ co n stru c tor ’ ] 를 문자열 로 변환한 후 1 과 연 결 한 것입니다. VeryPDF Demo 이러 한 문제 를 피 하기 위해서 는 for in 문에서 이런 유형의 문제를 피하기 위해서 사용 했던 h asOwnPro p e rty를 사용하거나 특정한 타입만을 골라서 작업할 수 있 습니 다 이번 예제의 경 우 아주 특별 한 경우가 아니므로 다음과 같이 수정함으로써 문제 를 간단히 해 결할 수 있습니다 i f ( t ypeof count [ word] ’ number ’ ) { 나쁘지만 사용해야 하는 쁨들뻐1 part히 | 179 VeryPDF Demo 醫셋 l , x>'1뀔 나쁜캠들 헌데 당선 께 꼭 좀 물어볼 말이 있는데 , 애 당초 대 처| 나의 어 떤 나쁜 점(bad parts) 때문에 나를 사랑하게 된 것 입니 까? - 윌리엉 셰익스피어, 헛소동 ‘팩 j’ .. 이번 부록에서 는 자바스크립트에서 문제가 되긴 하지만 쉽게 피 할 수 있는 속성 들을 설명할 것입니다. 여기서 얘기하는 부분들의 사용을 피함으로써 자바스크 립 트를 보다 좋은 언어로 만들 수 있고 더 나은 프로 그래머가 될 수 있습니다. 01 I == VeryPDF Demo 자바스크 립 트는 동동 비 교 연산자로 === / !==과 이것 들의 나쁜 쌍퉁이인 == / !=이 있습니다 이것 들 중에 앞선 한 쌍 만이 원하는 대로 제대로 통작합니다. 피연산자 두 개가 같은 데이터 타입이면서 같은 값일 때 는 참이 되고 1--- 는 거짓이 됩 니다. 나쁜 한 쌍도 두 피연산자의 타입이 같은 경우에는 바르게 동작합니다 하지 만 두 피연산자의 타입이 다른 경우 값들을 강제로 변환하여 비교합나다. 값을 변 환하여 비 교하는 규칙은 복잡하고 외우기도 쉽지 않습니다. 다음은 그 중에서 흥미 로운 몇 가지 예입니다 Ü.효t ;저도드 1 1.0 2 | I 181 // 거짓 ’0’ n U // 참 n U n u // 참 false ’ false ’ // 거짓 false ’0’ // false un d efined // 거짓 false // 거 짓 nul l null undefined o \ t\ r\n ’ 참 // 참 // 참 필자가 권하고 싶은 것은 결코 = = / != 를 사용하지 말고 대신에 항상 === / !==를 사용하라는 것 입니다 위에 있는 예 들은 연산자를 사용할 경우 모두 거짓입 니다. 02 I with 문 자바스크립트는 객체 하나에 속한 속성들을 접근할 때 간편함을 제공할 목적으로 with 문이 있습니다 하지만 이런 의도와는 달리 with 문은 때때로 예측 못한 결과 를 낳을 수 있기 때문에 사용하지 않는 것 이 좋습니다. VeryPDF Demo 다음과 같은 wit h with 문은, (obj) a b; 職 182 a u { 다음과 같은 의미입니다. (obj.a if a = undefined) obj.b { undefined ? b ob 그 .b ; } e l se { 。 bj . a obj .b undefined ? b obj.b; 그래서 결국 이 with 문은다음의 문장들중에 하나와같게 됩니다. a = b; a = obj.b ; 。 bj . a b; 。 bj . a obj . b ; 이 문장들 중에 어떤 문장으로 실행될지는 프로그램을 봐서는 알 수 없습니다. 또 한 프로그랩을 실행할 때마다 다르게 실행할 수 있고, 심지어는 프로그램을 실행하 는 동안에 도 달라질 수 있습니다 프로그램을 제대로 읽을 수 없고 어떻게 실행할 지를 예 측할 수 없다면 프로그램 이 원하는 대로 제대로 실행할 것이라고 확신할 수없습니다 VeryPDF간단하게 Demo 언 어 적인 측면에서 봐도 with 문은 자바스크립트 프로세서의 속도를 현 저히 느 리게 만듭니다 왜냐하면 with 문은 변수 이름의 어휘적 바인딩을 어렵게 하기 때 문입 니다. with 문은 그 의도는 좋았지만 오히려 없는 것이 더 나을 뻔 했 습니다. 나쁜점들 183 03 I eval eval 함수는 문자열을 자바스크립트 컴파일러에 넘긴 후 그 결과를 실행시컵니다. 이 함수는 자바스크립트에서 가장 오용되고 있는 기능 중 하나입니다 eval은 대부 분 자바스크립트에 대한 온전한 이해가 없는 사람틀이 가장 많이 사용합니다. 예를 들어, 만약 . (마침표) 표기법은 아는데 첨자 표기법은 모른다고 할 경우, 다음과 같 이 eval 함수를 사용하려고 할 것입니다. eva l ("myValue myObject ." + myKey + ";" ) ; 하지만 이것은 다음과 같이 하면 됩니다. myvalue myObj e ct[myKey ]; eval을 사용한 코드는 매우 읽기 어 렵습니다. 또한 eval 함수를 사용하면 단순한 할 당문 실행을 위하여 컴파일러를 기동해야 하므로 속도가 매우 느려질 수 있습니다. 또한 eval 함수는 JSLint(부록 C 참조)를 곤란하게 만들어서 문제점을 찾아내는 툴 의 기능을 현저히 저하시컵니다. 또한 eval 함수는 인수로 넘어옹 텍스트에 너무 많은 권한을 허용하기 때문에 애플 리케이션의 보안을 위태롭게 할 수도 있습니다. 그리고 이 함수는 VeryPDF Demo with 문이 하는 것처럼 언어의 성능을 저하시키는 원인이 될 수 있습니다. 함수 생성자도 eval의 또 다른 형태이며 같은 이유로 사용을 피해야만 합니다. 브라우저가 제공하는 setTimeout과 se tI nterval 함수는 문자열 인수나 함수 인수 를 취할 수 있습니다. 이 함수들에 문자열 인수를 제공하면 eval처럼 동작하게 되므 로, 문자열 인수를 넘기는 것은 피해야 합니다. 。 뼈 18 4 u 04 I continue continue contmue 문 문은 루프의 처음으로 제어를 이 통합니다. 필자는 리팩토링 을 통해 문을 제거했을 때 성능이 향상되지 않는 경우를 본 적이 없습니다 05 I 다음 case 절쩨 실행하는 switch 뭔때itch Fall Tlπough) switch 문은 FORTRAN IV가 go to 문을 다룬 이후에 고안됐습니다. 각각의 case 절은 명시적으로 벗어나게 하지 않으면 다음 case 절까지 계속해서 실행됩니다 어느 날 어떤 분이 필자에게 JSLint에서 다음 case 절까지 실행되는 case 절 에 대해 경고를 해야 한다고 제안하는 글을 쓴 적 이 있습니다 그 분은 이것이 매 우 일반적 인 오류의 원인이고 코드상으로는 찾기 어려운 오류라고 지적해 주셨습니다. 필자 는 모두 맞는 얘 기라고 답하면서 하지만 다음 case 절까지 실행시킴 a로써 얻는 이 득 이 그런 문제를 보상할 만큼 더 크다고 얘기했습니다. 다음날, 그 분은 JS Lint에 오류가 있다고 알려왔습니다. 그것은 잘못 확인된 오류였 지만 왜 그런가 자세히 살펴봤더니 , 다음 case 절까지 실행하는 case 문을 사용했 기 때문임이 밝혀졌습니다- 이때 큰 깨달음을 얻고 필자는 더 이상 이러한 유형의 case 음 문을 의도적으로 사용하지 않고 있습니다. 이러한 방침은 의도하지 않은 다 case 절까지 실행하는 패턴을 훨씬 쉽게 찾을 수 있게 합니 다 VeryPDF Demo 언어에서 가장 나쁜 점은 명백하게 위험하거나 불필요한 속성들이 아닙니다. 왜냐 하면 이러한 점 들은 쉽게 피할 수 있기 때문입니다. 그보다는 매 력적으로 보이는 폐단이 가장 나쁜 점입니다 이러한 속성들은 유용하기도 하면서 위험하기도 하기 때문 입니다 처 드 -」 버 나 D E 18 5 06 I 블록이 없는문장 i f/ while/ do/for 문은 블록을 사용할 수도 있고 문장 하나만을 사용할 수도 있습 니다. 문장 하나만을 사용하는 형식이 또 하나의 매력적인 폐단입니다 이 형식 은 문자 두 개를 아끼는 이점이 있지만, 좀 의심스러운 이접입니다. 이 형식은 프 로그램의 구조를 애매하게 만들어서 후에 작업하는 사람이 쉽게 버그를 만들 수 있게 합니다. 예를 들어 다음과 같은 코드는, if ( ok) t true ; 다음과 같이 될 수 있습니다 if (o k ) t true ; advance ( ); 이 코드는마치 다음과같이 보이지만, i f ( ok ) VeryPDF Demo { t true ; adva nce ( ) ; 실제로는다음과같은의미입니다. if ( ok) t 。 뼈 186 { true ; u a d van c e ( ); 이렇게 일을 처리하는 것처럼 보이 는 데 실제로 다르게 일을 처리하는 프로그램은 바르게 이해하기가 훨씬 어렵습니다. 그러므로 원칙적이고 일관된 블록의 사용은 프로그램의 이해 를 훨씬 쉽게 합니다 07 I ++ -증감 연산자를 사용하면 코드를 매우 간결한 스타일로 작성할 수 있습니다.C 같은 언어에서 는 다음과 같이 문자열 복사를 한 줄로 작성할수 있게 만들어 놨으며, 또 한이 런스타일을권장하기도 합니다 for (p src , q dest ; ! *p ; p ++ , q++) *q *p; 하지만 밝혀 진 바와같이 이런 것은부주의한자세였습니다. 심각한보안취약점을 만드는 대 부분의 버퍼 오버런 버그는 이와 같은 스타일의 코드 때문에 발생합니다. 펼자는 실무에서 + +와 --를 사용하게 되면 코드가 더 빽빽해지고 더 까다로워지 며, 보디 더 암호처럼 보이게 된다는 것을 경험 하게 됐습니다. 그래서 필자는 규칙 VeryPDF Demo 처럼 더 이상 증감 연산자를 사용하지 않습니다. 그 결 과로 필자의 코딩 스타일은 좀더 깔끔해 졌 다고 생각합니다. 08 I 비트연산자 자바스크 립 트는 자바와 같이 다음과 같은 비 트 연산자가 있습니다. 처 드근 쁘」 나 n 18 7 a nd & 。r xor not >> 부호 있는 오른쪽 시 프트 >> > << 부호 없는 오른쪽 시 프트 왼쪽시 프트 자바에서 비트 연산자는 정수에 대해서 동작합니다. 그런데 자바스크립트에는 정 수형은 없고 단지 배 정도의 부동 소수점 숫자형만이 존재합니다. 그래서 비트 연 산자는 대상이 되는 숫자를 일단 정수형으로 변환한 다음에 비트 연산을 수행하고 다시 원래 타입으로 되돌립니다. 대부분의 언어에서 비트 연산자는 하드웨어에 친 근하고 속도도 매우 빠릅니다. 자바스크립트에서 비트 연산자는 하드혜어와 전혀 동떨어져 있고 속도도 매우 느립니다. 자바스크립트가 비트 연산을 위해 사용되는 경우는매우드룹니다 그래서 자바스크립트 프로그램에서는 원래 &를 사용하는 경우보다 &&를 사용하 려다가 &로 잘못 사용하는 경우가 더 많습니다. 비트 연산자의 존재는 꼭 필요한 기능이라기 보다는 오히려 잠재된 버그를 만들어내기 쉽습니다. I 함수문장 vs 함수표현식 09 VeryPDF Demo 자바스크립트는 함수 문장과 함수 표현식 모두가 있습니다. 이 둘은 정확히 일치하 게 보이기 때문에 혼동이 됩니다. 함수 문장은 var 문장과 함수값 조합의 축약형입 니다. 다음과 같은 함수 문장은, function foo ( 뼈 188 Y < Q U ) {} 다음과 같은 의미라고 할 수 있습니다. var foo function foo ( {}; 이 책 전체에 걸쳐 필자는 두 번째 형식을 사용했습니다. 왜냐하면 두 번째 형식은 foo가 함수값 (func tion value) 을 가진 변수라는 것을 명확히 나타내기 때 문입 니 다. 자바스크립트라는 언어 를 잘 사용하기 위해서는 함수도 값 (valu e) 이라는 것을 이해히는 것 이 중요합니다 함수 문장은 위 로 끌어 올려지는 대상이 됩니다 ( hoisting). 이 말은 함수가 위치한 곳과 관계 없이 함수가 정의된 곳의 유효범위 가장 상위로 이 동된 다는 뜻입 니다 이러한 특징 은 함수를 사용하기 전에 반드시 선언해야 한디는 요구사항을 경감시 키는데 , 결국 필자 생각에는 구조를 엉성하게 만들 뿐입니다. 또한 이런 특징은 κ 문에서 함수 문장 사용을 금하게 됩니다. 밝혀진 바에 따르면 대부분의 브라우저에 서는 if 문 내에서 함수 문장 사용을 허용하고 있습니다. 하지만 이 렇 게 사용된 함 수 문장이 어떻게 해석되 는지는 브라우저마다 제 각각입니다 이런 점은 잠재적인 문제 를 발생 시 겁 니다 2 1 역자 주/ 그렇기 때문에 자바스크립트에서는 할수 호출이 할수를 정의하는 문장보다 앞에 있건 뒤에 있건 유효범위만 같 으면 문제가없습니다 VeryPDF2Demo 억자 주/ 힐수 var 문과 함수값을 사용하는 문장과 관련해서 I E는 조금 디르게 동작합니다 다음의 예를 보기 바랍니다 notPreDe fined () ’ v ar notPreDefined alert( " ok " ) ; 이 예는 function notPreDefin ed () ( notPreDefi ned() 부분에 함수가 정의되지 않았다는 오류가 빌생해야 정상입니다 왜냐하면 아래에 있는 함수 정의가 힐수 문장으로 정의된 것이 아니기 때문입니다 하지만 IE에서는 할수 표현식에 함수 이름을 지정만하면 힘수 문장으로 정의한 것처럼 해석하는 것으로 보입 니다 그래서 위의 코드를 fE에 서 확인하면 오류가 나지 않습니 다‘ 하지만 힘수 정의 부분을 다음 과 같이 하여 함수 이름을 빼면 오류가 발생합니다 va r no t Pr eDefi ne d alert (" ok " ) ; function () { 드 처 나 쁘」 D E 18 9 공식적인 문볍은 function 이라는 단어로 시작하는 문장을 함수 문장이라고 가정하 고 있기 때문에 문장의 첫 번째 부분에 함수 표현식을 사용할 수 없습니다. 이를 위 한 대안은 함수 표현식을 다음의 예처럼 괄호로 묶는 것입니다. (funct ion ( ) { va r hidden variable ; 이 함수는 환경에 영향을 미치 는 점들이 있지만 / / // 새 로운전 역변수를 // 추가하지는않음 }) ( ); I 데이터 10 타입 랩퍼 자바스크립트에는 일련의 데이터 타입 랩퍼들이 있습니다. 예를 들어 다음과 같은 문장은 랩핑된 값을 반환하는 valueOf 메소드를 가진 객체를 생성합니다 new Boo l ean (fa l se ) 이러한 랩퍼들은 완전히 필요끼F 없으며 때때로 혼란을 줄 수 있다는 것이 판명됐 습니다. new Boolean , new Numbe r., new String 둥을 사용하지 마십시오. VeryPDF Demo 또한 new Object와 new Ar ray 사용도 피하고 {}와 [)를 사용하기 바랍니다. 뼈 19 0 R u 11 I new 자바스크립트의 new 연산자는 피연산자의 프로토타입 멤버 들을 상속하는 객체를 생성하고 이 객체를 this에 바인딩하면서 피연산자를 호출합니다 이러한 호출은 new의 피연산자(생성자 함수)가 새 로 만들어진 객체를 원하는 대 로 커스터마이징 하여 반환할 수 있는 기회를 제공합니다. 만약 new 연산자를 빼먹게 되면 일반적인 함수 호출을 하게 되고 이 때 this는 새 로운 객체가 아니라 전역객체에 바인딩됩니다. 이렇게 되면 새로운 속성 을 초기화 할 때 전역변수에 접근하게 됩 니다 아주 안 좋은 결과입니다. new를 안 써도 컴파 일 시나 실행 시에 어떠한 경고도 없습니다. new와 함께 사용하기 위해서 만든 함수의 이름은 각 단어의 첫 글자를 대문자로 표기하고 그 외의 것 들에는 이러한 표기법을 사용하지 않는 것 이 좋습니다 (파스칼 표기법) 이러 한 코딩 규칙을 사용함으로써 new를 생략한 실수를 찾을 수 있는 단 서를 제 공할 수 있습니다. 물론 더 나은 정책은 new 연산자를 사용하지 않는 것입니다. 12 I void 많은 언어에서 yo id는 아무 값도 없는 데이터 타입입니다. 자바스크립트에서 yoid VeryPDF Demo 는 피연산자를 취한 후 unde fined를 반환하는 연산자입니다. 이 는 유용하지 도 않 고매우 혼동됩 니다 yoid 역시 피하는것 이 좋습니다. 드 -」 버 처 나 n E 19 1 VeryPDF Demo 醫셋 、 N. 0 . 1. X 빼 ]SLin t 무슨 착오 (error) 가 있어서 보는 것, 듣는 것이 뒤죽박죽 된 것일까? - 윌리엉 셰익스피어, 착오 희무 랑짧‘ C 언어가 나온지 얼마 안 됐을 때 초기의 컴파일러가 잡아내지 못하는 몇몇 공통적인 프로그래밍 오류가 있었습니다 그래서 소 스 파일 을 검색하여 이러한 오류들을 찾아주는 lint라는 부가적인 프로그램이 개발 됐습니다. C가 점점 발전하면서, 언어의 정의는 몇몇 안전하지 않은 요소들을 제거함으로써 강화되었고, 컴파일러는 경고를 알려주는 부분에서 더욱 발전하였습니 다. 결국 이상 필요하지 VeryPDF는더 Demo lint 않게 됐습니다. 자바스크 립트는 나이가 어린 언어입니다. 자바스크립트는 무거운 자바를 쓰기 에 적합하지 않은 웹 페이지 내의 작은 일들을 처리하도록 고안됐습니다. 하지만 자바 스크립 트는 매 우 재능 있는 언어 이고 현재 꽤 큰 프로젝트에서도 사용되고 있습니 다. 언어 를 쉽게 사용할 수 있도록 고안된 많은 속성들은 큰 프로젝트에서 는 골치 거리 로 작용하고 있습니다. 그 래서 자바스크립트를 위한 lint가 필요한데 , 자바스크 립트의 구문을 확인하고 검증해주는 JSLint가 바로 그것입니다. 써 ml L m 193 ]SLint는 자바스크립트의 코드 품질을 높 이기 위한 툴입니다. 이 툴은 소스 텍스트 를 검사하고, 만약 문제점을 발견하면 , 문제점을 설명하는 메시지와 소스의 대략 적인 위치를 반환합니다. ]SLint가 보고하는 문제점은 구문 오류뿐만이 아닙니다. ]SLint는 코딩 스타일과 구조적인 문제도 살펴봅니다. 이 툴은 검사하는 프로그램 전체가 온전히 문제 없다는 것을 증명하지는 못합니다. 다만 문제가 있을만한 부분 을 바라보는 또 다른 시각을 제공합니다. ]S Lint는 자바스크립트의 전문적인 부분집합을 정의하는데 이 부분집합은 ECMAScript 언어 명세 3번째 판에 정의돼 있는 것보다 훨씬 엄격한 부분집합입니 다. 이 부분집합은 9장에서 권고한스타일과거의 유사합니다. 자바스크립트는 엉성해 보이지만, 그 내부에는 우아하고 훨씬 좋은 언어가 내재돼 있습니다. ]SLint는 이러한 좋은 점들만을 사용하고 대부분의 엉성한 부분은 피할 수있게도와줍니다. ]SLint는 http://www.]SLint. c om/ 에서 사용할 수 있습니다. 01 I 정의되지 않은 변수와 함수 자바스크립트의 가장 큰 문제점은 전역변수에 의존하고 있다는 점입니다. 특히 묵 시적으로 선언되는 전역변수들은 더욱 문제입니다. 변수가 명시적으로 선언되지 (var VeryPDF않으면 Demo 문을 사용하여 선언되지 않으면) , 자바스크립트는 이 변수를 전역변수 로 간주합니다. 이런 특성은 오타가 난 이름이나 그 외 다른 문제들을 덮어버렬 수 있습니다 ]SLint는 모든 변수나 함수를 사용하거나 호출하기 전에 반드시 선언해야 함을 원 칙으로 하고 있습니다. 이러한 원칙은 묵시적인 전역변수를 찾을 수 있게 해줍니 다 또한 프로그램을 보다 읽기 쉽게 만들어줍니다. 빼 r 」 … ” 때때로 프로그랭 파일 하나가 다른 파일 에 정의 돼 있는 전역변수나 함수에 의존적 일 수 있습니다. 이 런 경우에 는 자신의 프로그램 이나 스크립트 파일 내에 정의돼 있지 않고 다른 곳에 있는 전역변수나 객체를 주석으로 표기하여 jSLnit에게 알려 줄 수있습니다 전역 선언 주석은 의도적으로 사용하는 모든 전역변수의 이 름을 열거하는데도 사 용할 수 있습니다 jSLint는 var 문을 생략했거나 잘못 입 력한 이 름을 구분할 때 이 정보를 참조합니다. 전역 선언 주석은 다음과 같은 형태입니다. /*global getEleme ntByAttr ibu te , breakCycles , han oi */ 전역 선언 주석은 /*global로 시작합니다와 g 사이에 빈 칸이 없다는 것 에 주의 해야 합니다 /*global 주석은 원 하는 만큼 사용할 수 있습니다 이 주석은 반드시 명시한 변수를사용하기 전 에 나타나야합니다. 일부 전역 요소들은 정의 돼 있는 것으로 가정할 수 있습니 다 (03. 옵션 절 참조) . 브라우저라고 가정하는 br owse r 옵션은 웹 브라우저에서 기 본으로 제공하는 w indow , document , ale rt 같은 표준 전역 속성들이 정 의돼 있다고 가정하고 검사 합니다. Rh ino로 가정하게 하는 rhino 옵션은 뻐ino 환경에서 제 공히는 전역 속성 들이 정의 돼 있다고 가정하고, Yahoo! 위 셋으로 가정하는 widget 옵션은 Yahoo ! 위셋 환경 에서 제공하는 전역 요소들 이 정의돼 있다고 가정합니다. VeryPDF Demo 02 I 잘못사용한이름찾기 자바스크립트는 엄격하지 않은 타입 체크를 하는 동적 객체 언어이기 때문에 컴파 일 시에 속성 이름 이 오타 없이 제대로 사용됐는지 알 수가 없습니다. jSLint는 이 러한 점과 관련하여 어느 정도 도움이 됩 니다 요 … 195 JSLint는 보고서의 마지막에 /*members* / 주석을 표시합니다. 이 주석에는 . (마침 표) 표기법과 배열첨자 표기법 객체 리터럴에서 속성의 이름 등에 사용된 모든 이 름과 문자열 리터럴들이 포함됩니다. 이 목록을 통해서 오타가 난 이름이 없나 확 인할 수 있습니다. 한 번만 사용된 이름은 이탤릭체로 표기해서 잘못된 부분을 쉽 게찾을수있게 합니다. /*members* / 주석을 아래와 같이 스크립트 파일 내에 복사할 수 있습니다. 그러 면 , JSLint는 이 목록과프로그램 코드에 사용된 속성 이름의 철자를 대조하게 됩니 다 이러한 방법으로 JSLint가 잘못된 이름을 찾을 수 있습니다. /*member s doTell , iDoDeclare , mercySakes , myGoodness , o hGoOn , wellShutMyMouth */ 03 I 옵션 JSLint는 사용자에게 맞는 자바스크립트 부분집합을 선택할 수 있게 옵션 객체를 받도록 구현돼 있습니다. 옵션은 스크립트의 소스 내에서도 지정할 수 있습니다. 스크립트 내에서의 옵션은 다음과 같은 형태로 지정할 수 있습니다. /*jsli n t nomen : t rue , ev il: false */ VeryPDF Demo 옵션의 설정은 /*jslint로 시작합니다와 j 사이에 빈칸이 없습니다. 설정 내용은 이름/값 쌍이 이어지 는 형태입니다. 이름은 JS Li nt 옵션의 이름이고 값은 true 나 false 입니다. 주석을 통한 옵션 설정은 옵션 객체보다 우선 순위를 갖습니다 모든 옵션의 기본값은 f외se 입니다. [표 C - lJ은 JSLint가 사용할 수 있는 옵션들을 보여 줍니다. 뼈 r 」 19 6 [표 C- 11 JS Li nt 옵션 의미 adsafe true 면 ADsafe.org 의 규칙이 강제로 적용됨 bitwise true 면 비트 연산자를 허용하지 않음 browser lrue 면 표준 브라우저 전역 속성들이 정의 돼 있다고 가정 빼 뼈 爛 빼 뼈 뼈 때 쩨 - 옵션 true 면 대문자 HTM L을 허용 true 면 debugger 문을 허용 true 먼 를 사용해야 함 lrue 면 eval 허용 true면 필터링하지 않은 for in 문 허용 tr 니 e 면 HTML의 일부분에 들어있는 자바스크립트 검사를 허용 1rue 먼 전역변수를 선언하는데 var를 사용하지 않아도 됨 true 면 if 문이 분리되는 것을 확인하지 않음 nomen true면 이름들을 확인 on true 면 HTML 이벤트 핸들러 허용 ’ pass ail 1rue 면 첫 번째 오류에서 검사를 멈춤 plusplus true 면 ++와 --를 허용하지 않음 rhino true 면 Rhino 환경 전역 요소들이 있다고 가정 undef ture 면 정의되지 않은 전역변수는 오류 white true 면 엄격한 공백 (whitespace) 규칙 적용 widget true 면 Yahoo! 위셋의 전역 요소들이 정의돼 있다고 가정 VeryPDF Demo 1 역자 주/ fragment 옵션은 다음과 같이 HTML에서 자바스크립트가 포함된 일부분만을 검사할 때 설정하는 옵션입니다 < HTML 대 그〉 <scrlpt> 자바스크렴트코드 <script> </HTML 태 그〉 싸 n m 197 옵션 04 I 세미콜론 자바스크립트는 C 유형의 구문을 사용합니다. 그래서 문장을 구분하기 위해서 세 미콜론을 사용합니다. 자바스크립트는 세미콜론 삽입 메커니 즘으로 세미콜론이 사 용되지 않았다고 생각되는 곳에 알아서 삽입합니다. 그런데 이러한 메커니즘은 위 험합니다. C처럼 자바스크립트도 ++, --, ( 연산자가 있는데 이 연산자들은 피연산자의 앞에 올 수도 있고 뒤에 올 수도 있습니다. 앞에 쓰인 것인지 뒤에 쓰인 것인지를 명확히 하는 것은 세미콜론입니다. 자바스크립트에서 라인피드 (LF) 는 공백 문자 (whitespace) 일 수도 있고 세미콜론 으로 동작할 수도 있습니다. 이러한 모호함은 의도와는 달리 서로가 뒤바뀔 여지가 있습니다. JSLint는 for , function , if, switch , try , while을 제외한 모든 문장의 끝에는 ;가 붙 VeryPDF 어 Demo 있어야 한다고 규정합니다. JSLint는 불필요한 세미콜론이나 빈 문장은 잘못된 것이라고간주합니다. 05 I 줄바뭄 세미콜론 자동 삽입 메커니즘으로 인해 발생히는 오류에 대해 좀더 방어적이 되기 위해서, JSLint는 긴 문장을 줄 바꿈할 때는 반드시 다음과 같은 구두점 문자나 연 19 8 뼈 산자 다음에 해야 하는 것을 원칙으로 하고 있습니다. C {)([ ' = <= >= += , == + <>? *= /= 잃 ^= */ 용 ^ 1 & 1= &= << >> && <<= >>= >>> >>>= jSLint는 긴 문장이 식별자, 문자열 , 숫자, 클로저 및 다음과 같은 접미 연산자 다음 에 줄 바꿈하는 것을 허용하지 않습니다. ++ -- 이러한 규칙들 없이 자유로운 줄 바꿈을 사용하려면 laxbreak 옵션을 켜면 됩니다. 세미 콜론 자동 삽입은 카피 앤 페이 스트(copy/ paste) 로 발생하는 오류를 덮어버 렬 수가 있습니다- 항상 연산자 다음에 줄 바꿈을 하면 jSLint가 이러한 오류를 찾 는데 도움이 됩니다. 06 쉽표 쉽표 연산자는 지나치게 까다로운 표현식의 원인이 될 수 있습니다. 이 연산자는 몇몇 프로그 래밍 오류를 숨길 수도 있습니다. jSLint는 쉽표를 연산자가 아니 라 구분자로 사용한 것만을 허용합니다 (for 문의 VeryPDF Demo 초기화 부분과 증가 부분은 예외입니다). jSLint는 배열 리터 럴에서 쉽표만 있고 배열 요소를 생략하는 것을 허용하지 않습니다 ([1, 2 ,3,1 나 [1 ,2 ,, 3J 같은 경우) 불 필요한 쉽표도 사용해서 는 안 됩니다 쉽표는 배열이나 객체 리터 럴 의 마지막 요 소 다음에 위치해서 는 안 됩니다. 이렇게 하면 몇몇 브라우저에서는 제대로 해석 하지 못합니다. 폐 … “ 199 07 I 뀔수블록 ]SLint는 κ 문과 for 문이 실행하는 문장들을 반드시 중괄호로 묶어 블록으로 만들 어야한다고규정합니다 자바스크립트는 다음과 같은 코드를 허용합니다 if (condition ) sta t ement ; 이러한 유형은 여러 프로그래머가 같은 코드로 함께 작업히는 프로젝트에서 오류 를 발생시키기 쉽다는 것이 판명됐습니다 그래서 ]SLint는 다음과 같은 형식 을 고 수합니다. if (condition) { s t atements ; 이러한 형식이 훨씬 좋다는 것은 경험이 말해주고 있습니다. 08 I 금지된블록 VeryPDF Demo 수많은 언어에서 블록은 유효범위 (s c ope) 를 갖습니다. 블록 내에서 정의된 변수 는 블록 바깥에서 볼 수 없습니다 자바스크립트에서는 블록이 유효범위를 갖지 않습니다. 단지 함수 유효범위만 존 재합니다. 함수 내에서 정의된 변수는 어디에서 정의됐던지 상관 없이 함수 내 모 든 곳에서 볼수 있습니다. 이러 한자바스크립트블록은 경험 많은프로그래머들에 게 혼란을 주고, 블록 유효범위를 가질 거 같이 보이지만 실제로는 그렇지 않기 때 뼈 문에 오류를 유발할 수 있습니다. r ZOO L JSLint는 function 문, if 문, switch 문, w hile 문, for 문, do 문, tIy 문에서만 블록 을 허용하고 그 외 다른 곳에 는 사용핸 것을 허용하지 않습니다. 물론 else “ 문 이나 forin 문에도 블록을 허용합니다. 09 I 표현식 문장 표현식 문장은 할당, 함수나 메 소드 호출, de le te 에 만 허용합니다. 그 외의 다른 모 든 표현식 문장은 오류로 간주합니다 10 I for in 문 for in 문은 객체가 가진 모든 속성의 이름들을 열거합니다. 불행 히도 for in 문은 프로토타입 체인을 통해 상속된 모든 멤버들도 열 거합니다. 또한 for in 문은 데이 터 속성 들에만 초점을 맞춰 열거 하고자 할 때 메 소드들까지 모두 열거해주는 안 좋은점 이 있습니 다, 모든 for in 문장의 몸체는 필 터링 기능을 하는 κ 문에 묶이는 것이 좋습니다 g 문 을 사용하여 필터링을 하면 특정한 타입이나 범위의 값만 선택할 수도 있고, 함수 들을 제외할 수도 있으며 프로토타입에 있는 속성들을 제외할 수 있습니다. 예를 다음과 VeryPDF 들면 Demo 같이 할 수 있습니다. for (n a me i n object ) if (ob ject . hasOwn Property(name)) 싸 엔 m ZOI 11 I switch 문 switch 문을 사용하면서 발생하는 가장 일반적인 오류는 각각의 case 절 마지막에 break 문을 두는 것을 잊어서 의도하지 않았는데도 다음 case 절까지 실행 (fallthrough) 을 하는 것입니다. JSωlt는 다음에 오는 c ase 나 은 default 바로 전의 문장 break , return , throw 중에 하나만을 허용합니다. 12 I var 문 자바스크립트는 함수 내의 어느 곳에서도 var를 사용하여 변수를 정의하는 것을 허용합니다 하지만 JSLint는 보다 엄격합니다. JSLint가 허용등}는 사항은 다음과 같습니다. • 변수는 한 번만 선언하고 사용하기 전에 var 문을 사용하여 선언할 것 . • 함수는 사용 전에 선언할 것. • 매개변수를 일반 변수로 재차 선언하지 말 것 그리고 JSLint가 허용하지 않는 사항은 다음과 같습니다. • arguments 배열을 var 문으로 선언하는 것 . • 변수를 블록 내에서 선언하는 것. 이유는 자바스크립트의 블록은 블록 유효 VeryPDF Demo 범위를 갖지 않기 때문. 블록 내에서 변수를 선언하면 예기치 못한 결과를 가 져올 수 있기 때문에 모두 변수는 함수 몸체의 상단에서 선언하는 것이 좋음. 「」 1 1 1 1 1 -- 뼈 1 니 m 13 I with 문 with 문의 의도는 깊게 중첩된 객체의 속성틀을 간단하게 접근하는 것입니다. 그 런데 이런 의도와는 달리 새로운 객체 속성을 설정할 때 매우 안 좋게 동작합니다. with 문을 결코 사용하지 마십시오 대신에 변수를 직접 사용해야 합니다 jSLinit는 with 문을 허용하지 않습니다. 14 I = jSLint는 if 문이나 w hile 문의 조건절에서 할당문을 사용하는 것을 허용하지 않습 니다 왜냐하면 다음과 같은 코드가, if (a b ) { 설제 로는 다음과 같은 조건절을 의도했는데 실수로 할당문을 사용한 것처럼 보이 는 경우가 많기 때문입니다. if ( a VeryPDF Demo b) { 만약 조건절 에서 할당문이 필요한 경우에는 다음과 같이 괄호로 묶어줍니다 if ( (a b)) { JSLint I 203 과 1= 15 과 연산자는 비교 전에 타입 변환을 합니다. 이러한 특성은 ‘ \ f\ r != \n\t ’ == 0 과 같은 경우를 참으로 인식하기 때문에 좋지 않습니다. 이 연산자들은 데이터 타 입 오류를 덮어버릴 수 있습니다. 다음과 같은 값들을 비교할 때는 항상 나 1-- 를 사용해야 합니다. 이 연산자들 은 타입을 변경하지 않고 비교합니다. o " 만약 undefined null false true 나 1= 를 사용하고 싶다면 짧은 형식을 사용하는 것이 좋습니다 즉 다음과 같이 하는대신에, ( foo != 0) 다음과 같이 사용합니다. ( foo) 그리고 다음과 같이 하는 대신에 , VeryPDF Demo ( foo 0) 다음과 같이 하면 됩니다. (! foo ) 항상 과 1-- 연산자사용을 우선 순위에 두는 것이 좋습니다. eqeqeq 옵션(== 과 !=를 허용하지 않음)을 설정하면 모든 경우에 m r 」 뼈 Z0 4 와 1-- 만 허용합니다. 16 I 라벨 자바스크립트에서는 모든 문장이 라벨을 가질 수 있고 라벨은 별도의 이름공간 (namespace) 을 갖습니다 JSLint는 이와 관련하여 좀더 엄격합니다. JSLint는 break 문으로 지정되는 switch 문, while 문, do 문, for 문에서만 라벨 사 용을 허용합니다. 라벨은 변수나 매개변수와 구분되어야 합니다 17 I 다음에 오는 코드가 정해진 문장 return 문, break 문, contmue 문, throw 문 등은 그 다음에 반드시 }나 case 또는 defa ult가 와야 합니다. 18 I +와-의 혼동 JSLint는 + 다음에 +나 ++가 오거나 - 다음에 -나 --가 오는 것을 허용하지 않습 니다- 잘못 위치한 빈칸은 + +를 ++로 변경할 수 있고 이렇게 발생한 오류는 찾기 가 어 렵습니다. 이러한 혼동을 피하기 위해서 괄호를 사용하는 것이 좋습니다. VeryPDF Demo 19 I ++와 -- ++( 증가)와 -- (감소) 연산자는 까다로운 부분을 야기하는 나쁜 코드의 원인으로 잘 알려져 있습니다. 이러한 연산/(}는 바이러스나 그 외 다른 보안적 위험을 낳는 잘못된 아키 텍처에 버 금갈 정도로 안 좋은 것입니다. JSLint의 plusplus 옵션을 설 정하면 이 연산자들 사용을 금합니다 JSLint I 205 20 I 비트연산자 자바스크립트는 정수형 데이터 타입이 없음에도 불구하고 비트 연산자가 있습니 다. 비트 연산자는 피연산지를 부동 소수점에서 정수형으로 돌려 연산을 한 후 다 시 되돌립니다 그래서 자바스크립트의 비트 연산은 C나 그 밖의 다른 언어들에서 처럼 효율적이지 않습니다 이들은 브라우저 애플리케이션에서는 거의 유용하지 않습니다. 논리 연산자와 비슷한 점은 오히려 일부 프로그래밍 오류를 감출 수 있 습니다. bitwise 옵션을 설정하면 비트 연산자를 허용하지 않습니다. 21 I eval eval 함수와 그의 사촌들 (Function , setTimeout , se tInterval) 은 자바스크립트 컴 파일러를 접근하게 합니다. 이 함수들은 때때로 유용하지만, 대부분의 경우 아주 나쁜 코딩의 단초가 될 수 있습니다. eval 함수는 자바스크립트에서 가장 오용하고 있는 기능 중 하나입니다. 22 I void C 계열의 언어 대부분에서 void는 데이터 타입입니다. 자바스크립트에서 void는 항상 undefined를 VeryPDF Demo 반환하는 전치 연산자입니다. void는 혼란만을 가중하고 유용 하지 않기 때문에 JSLint는 이 연산자를 허용하지 않습니다. 23 I 정큐표현식 정규 표현식은 간결하고 암호처럼 보이는 표기법으로 작성됩니다. JSLint는 잠재적 인 문제를 야기할 수 있는 문제들을 찾습니다. 또한 JSLint는 명시적인 이스케이프 4 @ 「」 1 뼈 를 권고함으로써 가시적인 모호함을 해결하려고 합니다. 정규표현식 리터럴을위한자바스크립트의 구문은 /를 너무 많이 사용하게 합니다. = 모호성을 피하기 위해 jSLint는 정규 표현식 리터 럴 앞에 올 수 있는 문자로 ( 만을허용합니다 24 I 생성자와 new 생성자는 new와 함께 사용되도록 고안된 함수입니다. 전치어 new는 함수의 프로 토타입 에 근거하여 새로운 객체를 생성하고 이를 함수의 묵시적인 this 매개변수 에 바인딩합니다 만약 new를 빼먹게 되면 새로운 객체는 생성되지 않고 this는 전 역객체에 바인딩됩니다. 이것은 심각한 실수입니다. jSLint는 머리 글자를 대문자로 사용하는 표기법으로 생성자 함수의 이름을 짓도록 강요합니다 jS Lint는 이 름의 머리 글자가 대문자인 함수를 new 없이 호출하는 것 을 허용하지 않습니다 또한 이외는 반대로 이름의 머리 글자가 대문자가 아닌 함 수가 new와 함께 호출되는 것도 허용하지 않습니다. jSLint는 랩퍼 형식인 new Number , new String , new Boole an을 허용하지 않습 니다. o사용 ) . jSLint는 new Obj ec t도 허용하지 않습니다(대신에 jSLint는 new Array도 허용하지 않습니다(대신에 [] 사용) . VeryPDF Demo 25 I 예측하지 않음 jSLint는 변수가 사용되기 전에 값이 할당되는지를 분석하지 않습니다. 왜냐하면 많은 프로그 램에서 당연한 기본값으로 생각판 unde fine d가 기본값으로 할당되 기 때 문입 니다. m1 Q L m m jSLint는 전역적인 분석을 하지 않습니다. new와 같이 사용된 함수가 실제 생성자 인지 또는 메소드 이름의 철자가 맞았는지 등을 확인하려고 하지 않습니다(생성자 와 관련해서는 대문자 표기법은 확인합니다) . 26 I HTML jS Lint는 HTML 텍스트를 다룰 수 있습니다. <script) ... </ script) 태그 안과 이 벤트 핸들러로 지정된 자바스크립트를 분별해낼 수 있습니다. 또한 다음과 같은 내용들을 조사하여 자바스크립트를 방해하는 것으로 알려진 문제들을 찾을 수 있 습니다. • 모든 태그 이름이 소문자인지 확인 • 닫는 태그가 있는 모든 태그에 닫는 태그가 있는지 확인 • 모든 태그가 제대로 중첩됐는지 확인 • 리터럴 〈를 위해 엔티티 <가사용됐는지 확인 jSLint는 짧TML이 요구하는 수준까지 확인하지는 않지만 유명한 브라우저들보다 더 엄격합니다. jSLint는 또한 문자열 리터 럴에서 <1가 나타니는지 도 검사합니다. 항상 </ 대신에 〈\/를 사용해야 합니다. 부가적인 \를 자바스크립트 컴파일러는 무시하지만 HTML VeryPDF Demo 파서는 그렇지 않습니다. 옵션 중에는 대문자 태그를 허용하는 옵션이 있습니다 또한 인라인 Hπ1L 이벤트 핸들러를 허용하는 옵션도 있습니다. m 「」 J 뼈 7 - 27 I JSON ]SLint는 또한 ]SON 데이터 구조가 제대로 구성됐는지 확인할 수 있습니다. ]SLi nt 가 살피는 첫 글자가 {나 [면 ]SLint는 ]SON 규칙을 엄격하게 적용합니다.]SON은 부록 E에 자세히 설명합니다. 28 I 보고서 ]SLint가 분석을 모두 마치면 함수 보고서를 생성합니다. 이 보고서는 각각의 함수 에 대해 다음의 항목들을 열거합니다. · 함수가시작핸줄변호 • 함수 이름. 함수 이름이 주어지지 않은 함수 (anonymous) 이면 함수 이름을 예 측하여 표시 ·매개변수 • Closure: 함수 내에 선언되어 내부 함수에서 사용되는 변수와 매개변수 • Variables: 함수 내에서 선언되어 함수에서만 사용되는 변수 • Unused: 함수 내에서 선언됐지만사용되지 않은 변수. 이로 인해 오류를 발 견할수도있음 • Outer: VeryPDF Demo 함수 내에서 사용되지만 다른 함수에서 선언된 변수 • Global: 함수에서 사용된 전역변수 • Label: 함수에서 사용된 라벨 또한 보고서에 는 사용된 모든 속성 이름이 포함됩니다. 」 m Q1 m m VeryPDF Demo 醫찮썩 A.P.P.E.N . D.I .X 떼 구푼 다。 1 òì2랜 그렇게 몽짓만으호 말을 하는 비탄의 도연 같은 너는! - 윌리엉 셰익스피어, 타이터스 앤드로니커스 구문 다이어그램 을 참고하기 쉽 게 A-Z 그리고 가~하 순서로 배치했습니다. r-(프똥~ case G키 절 VeryPDF Demo do 문 래 그 어 이 다 1 D 2.Il 초기화 표현석문장 조건 표현식 증가 표현식 문장 빡혐 - ” }션 /、 식 - L..!-. 협--0-1 표현식 망꿇팩끼많L 뉴-표략곤꾀 { swítch 문 VeryPDF Demo throw 문 뼈 n ν 212 표현식 } G녁 try 문 }세닝 /‘ L-' var 문 wh ite 문 VeryPDF Demo 편다이어그램 | 2 13 공백 (whites pace) 줄몰문자를 제외한모든문자 *와 /를제외 한 모든문자 리터렬 숫자리터럴 문자열 리터럴 객체리터럴 배열리터럴 할수 정규표현식 리터럴 VeryPDF Demo F굉 l 며운「 ( 뼈 2 14 n ] I ~I--I_ Lø ”고f ₩ 그리고 제어문지를 제외한 모든유니코드문자 이스케이프된문자 “과 ₩ 그리고 제어문자를 제외한 모든유니코드문자 이스케이프된문자 C그 Af ;,:- ζ〉 표현식문장 벗어나는문장 try 운 if -며 switch 문 while 문 for 문 VeryPDF Demo d。문 벗어나는문징 break 문 return 문 throw 문 버 편다이어그램 | 2 15 배열 리터럴 뉴o 표현식 | @키 l -()---- i - - -트 E 장 -무-- H-{ 「 붉 • ) - 뉴t혈혈?망」 }十키깅 t묘빨j 숫자 E 터럴 뉴뉴-내 정수 이름 VeryPDF Demo m n ν 뼈 zl6 -수카 소수 →--ι카 I수 : 11 이스케이프된문자 큰따옴표 작은따옴묘 역슬래시 4J 슬래시 역스페이스 타효표|드 LF CR 라-월 4자리의 16진수 이항연산자 논리적 or 나머지 큰 작은 VeryPDF Demo 전 치 연산자 피연산자의 타입 숫자로지정 + 부정 논리적 not 문다이어그램 | 2 17 정규표현식 그룹 캡처 정규표현식선택 비캡처 긍정형룩어헤드 부정형룩어헤드 정규표현식 리터럴 정규표현식선택 /₩ [lO O?+*1 과 제어문자를 제외한 모든 유니코드 문자 정규 표현식 클래스 내의 이스케이프 정규 표현식 클래스 내의 이스케이묘 역스페이스 닙Z 폼피드 -.ζj f VeryPDF Demo n r LF 숫재0-9) CR 공백 (whitespace) EH t=l 단어문자 t 리터럴 모든특수문자 뼈 218 n u 정규표현식선택 H 정규표현식시켠 A 'L o 정규표현식수랑자 소 요 -시 「 U이 저。 쿼」 규 훨 스- 묘 시「 혀」 규 저。 , 정규표현식수량자 /₩ []O{}?+치과 제어문자를 II 제외한 모든 유 LI .n드 문자 II 정규표현식이스케이프 VeryPDF Demo 정규표현식문자클래스 정규표현식그릅 구문 다이어그램 ZI 9 정규표현식 이스케이프 폼띠드 부정 단어경계 f LF 슷재 0-9) CR 공백 (whitespace) 댐 단어문자 n r t 리터럴 모든특수문자 후위참조 정수 VeryPDF Demo 뼈 220 n u 표현식 전치연산자 이항연산자 세부지정( 또는 [ l) 세부지정( 또는[]) 표현식문장 VeryPDF Demo 세부지정( 또는[]) 함수몸체 다 얘 괜 ZZI 함수옴체 뉴-ø-케 H var 문 문장 !---Ø 호출 F굉 L.rJ VeryPDF Demo 뼈 222 n ] 표현A 바←--0 훨뺨쫓 、 / / A.P.P.E.N.D.I.X 법 ]SON 그만 가보겠다. 이렇게 절박한 비상 사태 하에서는 오랜만에 만난 친구로서 흉 금을 털어놓고 즐겁게 얘기를 할래야 할 수가 없구나. 신은 그러한 단란을 후일 에 마련해 주시겠지! 자, 한 번 더 잘 있거라. 용감히 싸워라. 성공을 빈다! - 윌리엄 셰익스피어. 리차드 3세 짧3’ ]SONüavaScript Object Notation) 은 경량화된 데이터 교환 형 식입니다. 이 형식은 자바스크립트의 가장 좋은 점 중에 하나인 객체 리터럴 표기법에 기초하고 있습니다. ]SON이 자바스크립트의 부분집합이기 는 하지만 언어에 독립적입니다 ]SON은 프로그램이 (오늘날 사용되는) 어떤 프로 그래밍 언어로 작성됐던지 관계없이 서로 데이터를 교환하는데 사용할 수 있습니 다.]SON은 텍스트 형식이기 때문에 사람이나 기계가 모두 읽을 수 있고 구현이나 사용이 쉽습니다 ]SON과 관련된 자료들은 http://www .JSON .org/ 에 있습니다. VeryPDF Demo 01 I JSON 구문 ]SON은 객체, 배열, 문자열, 숫자, 불리언 (true/떼se) , null 이렇게 여섯 종류의 값이 있습니다. 공백 문자(빈 칸, 랩, CR, LF) 는 값의 앞이나 뒤에 삽입할 수 있습니다. 이 런 규칙 하에 공백 문자를 적절히 사용하면 ]SON 텍스트를 사람이 보다 쉽게 읽을 수 있습니다. 공백 문지는 전송이나 저장 비용을 줄이기 위해 생략할 수 있습니다. m 223 JSON 값 JSON 객체 JSON 배열 JSON 문자열 JSON 숫자 ]SON 객체는 이름/값 쌍들을 순서 없이 가지고 있는 컨테이너입니다. 이름은 문자 열이고 값은 배열과 객체를 포함한 모든 ]SON 값이 가능합니다 ]SON 객체는 원하 는 만큼 중첩해서 사용할 수 있습니다. 하지만 중첩 단계를 상대적으로 얄게 유지 하는 것이 일반적으로 가장 효율적입니다. 대부분의 언어는 ]SON 객체를 쉽게 사 상 Cmapping) 할 수 있는 객체, 구조체, 레코드, 사전, 해시 테이블, 속성 리스트, 연 관배열둥이 있습니다. JSON 문자열 ‘JSON 값 VeryPDF Demo ]SON 배열은 순서를 가진 값들의 연속체입니다. 배열 요소의 값은 ]SON 배열이나 객체를 포함한 모든 ]SON 값이 가능합니다. 대부분의 언어는 ]SON 배열을 쉽게 사 상 Cmapping) 할 수 있는 배열, 벡터, 리스트, 시권스 등이 있습니다. 職 」 r 224 뼈 $ ONN / l l l l l 4 JSON 값 •------CD 나녁 G ]SON 문자열은 큰 따옴표로 묶입니다. 이스케이프를 위해서는 \를 사용합니다. ]SON은 /가 이 스 케이 프되는 것을 허용하기 때문에 ]SON을 HTML <SC1ψt ) 태그 내에 넣을 수 있습니다. <script) 태그 내에 ]SON을 넣는 경우 주의할 점은, HTML 이 <l script ) 를 제외하고는 <1를 허용하지 않는다는 것입니다. 그래서 ]SON에 </ 가 포함된 경우 문제가 될 수 있지만, ]SON은 </를 〈\/로 표기판 것을 허용하기 때문에 HT빠에 위배되는 </를 〈\/로 이스케이 프하여 사용할수 있습니다. “와 / 그 리고 제어문자를 제외한 모든 유니코드 문자 큰따옴표 다걱렐스| }확쇠 바월lljl OI스 VeryPDF Demo 하휠|드 한上E 간주E -/「、 I。여 EtjH 다 4자리의 16진수 mN 225 ]SON 숫자는 자바스크립트의 숫자와 유사합니다. 정수에서 앞에 0을 붙이는 것을 허용하지 않는데 일부 언어에서는 앞에 0을 붙이는 것 이 8진수를 나타내기 때문입 니다. 이러한 종류의 기수(진법) 혼동은 데이터 교환 형식에 는 바람직하지 않습니 다. 숫자는 정수, 실수 또는 그보다 더 정밀한 값 모두 가능합니다. JSON 숫자 소수 지수 여기까지가 ]SON의 전부입니다 ]SON을 설계할 때 목표로 삼은 것은 최소화, 이 식성, 텍 스트 기반, 자바스크립트의 부분집합이었습니다. 상호 운용을 위해 동의해 야 할 것 들이 적으면 적 을수록 더 쉽게 운용될 수 있습니다. " firs t ": VeryPDF Demo " Jerome 11 I " mi d dle ": " Lester " , " last ": " Howard " , " nick - name ": " Curly " , " born ": 1903 , " died " : 1952 , " quote ": " nyuk - nyuk - nyuk !" 226 뼈 " fir st": " Harr y" , " middle ": " Moses " , " last ": " Howard " , " nick - name ": " Moe " I E " born ": 1897 , " died ": 1975 , " quote " : 씨 hy , you 1" " first " : " Louis " , " last ": " Feinberg " , " nick - name ": " Larry " , " born ": 1902 , " died ": 1975 , " quote ": " 1 ’ m sorry . Moe , it was an accident !" 02 I JSON을 안전하게 사용하기 ]S O N은 자바스트 립 트이기 때문에 특별히 웹 애플리케이션에서 사용하기가 쉽 습 니다.]SON 텍 스트는 다음과 같이 eval 함수를 통해 유용한 데이터 구조로 전환될 수있습니다. v ar myData eva1( ’ ( ’ + myJSONText + ’ ) ’ ) ; 0S0N 텍 스트에 괄호를 붙이 는 것은 자바스트립트 문법에서 모호함을 피하기 위 입 니다J VeryPDF해서 Demo eval 함수는 보 안에 있 어서 치 명적인 문제점이 있습니다 그렇다면 eval 함수 로 ]SON 텍 스트를 파성하는 것 은 안전할까요? 현재 웹 브라우저에서 서버로부 터 데이터 를 얻는 가장 좋은 기술은 XMLHttpRe que s t를 사용하는 것입니다 때LHttpRe qu es t는 해당 HrML이 속하는 서버로부터만 데이터를 수신할 수 있습 니다. 서버 로부터 보내져서 eval되 는 텍스트는 원래 HTML 만큼이나 안전합니다. 하지 만 서버가 문제가 있는 경우를 생각해 보겠습니다. 만약, 서버가 기 능을 제대 로 못하는 불완전 한 경우라면 어 떻게 될까요? m 227 불완전한 서버는 ]SON 형식을 제대로 만들지 못할 수 있습니다. 서버가 적절한 ]SON 인코더를 사용하여 만들지 않고 아무렇게나 문자열을 합쳐 ]SON 텍스트를 만든다면 의도하지는 않았지만 결과적으로 위험한 물건을 클라이언트로 전송하게 될 수 있습니다. 또한 서버가 프록시 서버 역할을 하여 ]SON 형식이 제대로 갖춰졌 는지 확인하지 않고 받은 것을 그대로 전송한다면 이 역시도 위험 요소를 보내는 것이 될수있습니다. 이러한 위험은 eval 대신 ]SON.parse 메소드를 사용하여 피할 수 있습니다 (http://www.]SON.org/json2.js 참조). ]SON.parse는 텍스트 안에 위험해 보이 는 것이 있으면 예외를 발생합니다. 불완전한 서버에 대웅하기 위해서 항상 eval 대 신 ]SON.parse를 사용할 것을 권해드립니다. 이러한 방법은 브라우저가 다른 서버 에서 데이터를 직접 받는 것을 허용핸 때가 되면 안전을 위해 더욱 유용합니다. 외부 데이터와 innterHTML 사이에 상호작용을 할 때 또 다른 위험이 있습니 다. 일반적인 Ajax 패턴은 서버에서 HTML 텍스트를 보내고 이를 HTML 요소의 innerHTML 속성에 할당하는 것입니다. 이러한 방법은 아주 나쁜 관행입니다. HTML 텍스트에 (script) 태그나 그에 상용하는 부분이 속해 있는 경우 악의적인 스 크립트가 실행될 수 있습니다. 이 역시도 물론 불완전한 서버로 인한 문제입니다. 특별히 어떤 점이 위험할까요? 악의적인 스크립트가 자신의 페이지에서 실행되 면, 페이지의 모든 상태와 기능에 접근할 수 있습니다. 이 스크립트는 서버와 상호 작용을 할 수도 있는데 서버는 요청이 제대로만 오면 이 요청이 악의적인 스크립 VeryPDF트가 Demo 한 요청인지 그렇지 않은지를 구별할 수 없습니다 악의적인 스크립트는 전 역객체에도 접근할 수 있는데 이렇게 되면 클로저 (closure) 로 숨겨진 변수를 제 외한 애플리케이션의 모든 변수를 접근할 수 있게 됩니다. 악의적인 스크립트는 document 객체에도 접근할 수 있습니다 document 객체에 접근할 수 있다는 의 미는 사용자가 보는 모든 것에 접근할 수 있다는 의미 입니다. document 객체에 접근할 수 있으면 사용자에게 원하는 내용을 (경고창 동을 통해) 보여줄 수도 있는 데 이러한 내용은 주소가 이동돼서 보이는 것이 아니기 때문에 피싱 필터에도 감 지될 수 없고 결국 사용자는 이 내용을 바른 내용으로 믿게 될 수 있습니다. 또한 뼈 생 」 F docume nt 객체는 네트워 크를 사용할 수 있게 도 해서 보다 악의 적 인 스크립트를 로딩하거 나 방화벽 내의 사이트들을 검색하고 이 렇게 알게 된 정보들을 외부로 보 낼수있습니다. 이러한 위험은 모두 자바스크 립 트의 전역객체로 인한 직접적인 결과인데 자바스 크립트의 많은 나쁜 점들 중에서도 단연 가장 나쁜 점입니다. 이러한 위 험은 Ajax 나 }SON 또는 자1LHttpRe uqesty- Web 2.0 (혹은 뭐라 지 칭하든) 때문이 아닙니 다. 이러한 위 험은 자바스크립트가 소개된 이 후로 계 속해서 브라우저에 내재돼 있 었고 자바스크립 트가 대체되기 전까지는 계 속 있게 될 위험입니다. 그 러 므로 주의 해야 합니다. 03 I JSON 끄f서 다음은 자바스크립트로 구현한 }SON 파서입니다. v ar jso n parse 1/ JSON fu nction () 텍 스트를 파싱하여 자바스크립 트 데이터 구조를 반환하는 함수 // 재귀적 하향 방식의 파서 1/ VeryPDF Demo 선역변수 생성 을 피하기 위해서 함수 내에 또 다른 함수를 정의할 것임 v ar at , // // ch , 현재 문자의 인텍 스 현재 문자 escapee '"’’ \\ ’ : ’ \\ ’ , ’/ ’ : b: ’b ’ f : ’\ f ’ n ’\n ’, r : ’ \r ’ t : ’\ t ’ f l mN Z2 9 text , error function (m) // 잘못된 것 이 있을 때 는 error 호출, throw { ’ SyntaxError ’ name : I message : m, next at : at , text: text function (c) // 매개변수가 주어지면 , 현 재 문자와 일 치하는지 검 사 if (c && c ’ ch) { error ("Exfected I I ’ + C + "’ instead of // 다음 문자를 취 함 더 이 상 문자가 없는 경우 빈 문자열 반환 ch text . charAt(at) ; at += 1 ; return ch ; VeryPDF Demo number function () // 숫자값파싱. var number , string "; ’- ’ ) { ’-’; next( ’ - ’ ) ; if (ch string 뼈 rF 」 23 0 I I ’ + ch + "’" ) ; (ch >= ’ O ’ && ch <= ’ 9 ’ ) whil e { string += ch ; nex t () ; if ’.’) { (c h string += ’ . ’ ; while ( ne xt() && ch >= ’ O ’ && ch <= ’ 9 ’ ) { strin g += ch ; if ’ e ’ I I ch ( ch ’E ’ ) { stri ng += ch ; next () ; if ’ ’ II ch ( ch ’+’) { strin g += ch ; ne x t () ; (ch >= ’ 0 ’ && ch <= ’ 9 ’ ) whi l e { stri ng += ch ; next () ; number if +str ing ; (i sNaN (number )) { error ("Bad number " ) } else { retur n nu mber ; VeryPDF Demo str ιn g functi on () // 문자열 파싱 var h ex , 1 , string uffff; 뼈 23 1 // 문자열을 파싱할 때 , “와 \를 찾아야 함 if ’” ’) (ch whi l e { (next ()) if { ’”’) { (ch next() ; return string; } else if ’ \\ ’ ) (ch { next () ; if ’U ’ ) { (ch uffff for 0; (i 0; he x if i < 4; i += 1) parselnt(next() , { 16) ; ( ! isFinite(he x )) break ; uffff uffff * 16 + hex ; string += String.fromCha rCode(uffff) ; } else if (typeof escapee[ch] string += escapee[ch] ; } else { break ; } else { string += ch ; error ( " Bad string " ) VeryPDF Demo white function () // 공백 문지를건 너 띔 while (ch && ch <= ’ next () ; m r 」 뼈 232 ’) { ’ string ’ ) { word // functι 。 n true 나 false 나 () { nu l l switch ( ch) { case ’ t ’ : next ( ’ t ’ ) ; next ( ’ r ’ ) ; next ( ’ U ’ ) ; next ( ’ e ’ ) ; return true ; case ’ f ’ : next ( ’ f ’ ) ; next ( ’ a ’ ) ; next ( ’ l ’ ) ; next ( ’ s ’ ) ; next ( ’ e ’ ) ; return false ; case ’ n ’ : next ( ’ n ’ ) ; next ( ’ U ’ ) ; next ( ’ l ’ ) ; next ( ’ l ’ ) ; return null; error ("Unexpected "’ + ch + fI"’ ) ; VeryPDF Demo value , // arra y function 함수를 위한 변수 va l ue () // 배열 파싱 L L(• ( 아없 var array [] ; [ = ( [ { ) mN Z33 에 이없 다 뻐묘 I ( ! N ) ., m t r (ch) { ; ////l 뼈 while ] 빈 m : { array.push(value()) ; white (); ’]’) { next( ’ ] ’ ) ; (ch if return array ; next( ’ ,’); white() ; error( " Bad array ") 。 bj ect function () { // 객체 파싱‘ var key , {}; 。 bject if ’{’) { (ch ne x t( ’ { ’ ) ; white (); VeryPDF Demo if ’}’) { (ch next( ’ } ’ ) ; return obj ect; while (ch) key // 빈 객체 { string() ; white () ; next( ’ : ’ 。 bj ect [key] whi te () ; 뼈 C 2. 34 L value () ; 이 - t L } ) { ne x t ( ’ } ’ return object; next( ’ r ’); white() ; error( " Bad object " ) ; value function () // JSON 값 파싱 유효한 값은 객체, 배열 문자열, 숫자, 단어, white() ; switch ( ch) case ’ { ’ : return object() ; case ’ [ ’ : return array() ; case return string() ; case ’ - ’ : return number() ; de f ault : return ch >= ’ 0 ’ && ch <= ’ 9 ’ ? number() word() ; VeryPDF Demo // j son parse 함수를 반환 위에 정의한 모든 함수와 변수에 접근 가능 return function (source , reγiver) var result ; text at source ; 0; ch result ' . value() ; JSON I 235 white(); if (ch) ( error( " Syntax error ") // reviver 함수가 있으면, 파싱한 결과를 재귀적으 로 탐색하여 // 각각의 이 름/값 쌍을 reviver 함수로 보내 변환하게 하는 // walk 함수를 호출하여 반환 walk 함수를 호출할 때 처음 값으로 빈 키에 값은 // 반환값 (result) 을가진입시객체를념김 revlver 힘수가없으면단순히 result를 반환 return typeof reviver ’ function ’ ? function walk(holder , key) var k , v , value holder[key]; if (value && typeof value for (k in value) ’ 。 bject ’ ) { if (Object.hasOwn Property.call(value , k)) ( v walk(value , k); if (v ’ undefined) value[k ] v; } else ( delete value[k] ; return reviver.call(holder , key , value); }({": result) VeryPDF Demo } () . , 뼈 F 」 236 , ") result; ν 짧짧빼뿔 R템 undefìned 4 1. 44 값갱신 42 1= 연산자 181 1== 연산자 181 & 188 && 34 + 34 , 173 ++ 187 += 32 << 188 구문 다이어그랩 꼬리 재귀 최적화 뀐 동등 연산자 181 법 라벨 205 리플렉션 45 랩퍼 190 177, 181 >> 188 >>> 188 [) 64 공백 20 32 ? 211-222 33 핍 10。 문자타업 ^ 188 문법 1 188 11 42 - 188 / 34 /' •/ 21 25 19- 38 표현식 33 함수 37 리터럴 36 이름 숫자 톨겐 21 23 메소 드 음수 계숭 64 ‘ 80 객체 리터럴 36 ‘ 100 객체 기술자 객체 리터 럴 36 다이어그랩 해석 방법 문장 26 문자열 24 length 속성 25 공백 20 묵시적 전역변수 168 메모이제이션 78 87 객체 11 연산자 객체 생성 위임 44 42 40 VeryPDF Demo delete 연산자 47 열거 46 for in 문 함수 49 메소드 진역변수 47 떼소드 프로토타입 체인상의 속성 prototype 22 프로토타엽 43 연결 44 참조 43 리플렉션 45 속성 값읽기 41 19 메소드호출패턴 52 46 hasOwnProeprty 리터럴 40 속성 41 24 23 45 44 array.concat() 131 array.jo in() 132 array.pop() 132 array.push () 133 array. reverse() 133 array.shift() 134 array.slice() 134 array.sort() 135-138 array.splice() 139 -140 array. unsh ift ( ) 141 function.apply() 141 237 number.toExponential() 142 number.toFixed() 143 number.toPrecision() 143 number.toString() 144 。 bject‘ hasOwnProperty() 144 regexp.exe c( ) 145 regexp.test() 147 string.charAt() 148 string.charCodeAt() 149 string.concat() 149 String .fromCharCode() 156 string .i ndexOf() 149 string .l astlndexOf() 149 string .l ocaleCompare() 150 string.match() 150 string.replace() 151 string.search() 153 strmg ‘ slice() 153 string.split() 154 string.substring() 155 string.toLocaleLowerCase() 155 string.toLocaleUpperCase() 155 string.toLowerCase() 156 string.toUpperCase() 156 모률 72-74 문장 블록 27 29 , 31 case 절 29 catch 절 31 do 27 , 30 for 27 , 29 for in 30 if 28 라벨 31 retum 31 switch 27 , 28 , 31 then 블록 28 throw 31 VeryPDF Demo try 31 var 26 while 27 , 29 문자열 24 , 39 빈문자열 28 length 속성 25 bre따( m 배열 리터렬 37 배열 새로운항목추가 102 배열의 크기와 차원 108 객체와 배열의 혼통 104 delete 연산자 103 Z3 8 다차원 배열 열거 104 length 속성 리터럴 100 108 101 에소드 106 Object.create 메소드 107 splice 메소드 103 typeof 연산자 105 undefmed 값 108 비트 연산자 187 , 206 블록주석 21 , 160 블록 유효범위 66 , 165 블록없는문장 186 블록 28 , 200 불리언 39 빈문자열 28 부동소수점 174 반복문 29 , 30 m 생성자 55 정의 83 생성자함수 위험 86 new 전치 연산자 86 생성자호출패턴 54 실행문 26 상속 함수를 사용한 방식 90-95 객체 기술자 87 부속품 96-98 프로토타입 방식 88 의사 클래스 방식 82 - 86 , 95 숫자 23 , 39 숫자객체 101 핍 아름다운 속성에 대한 단상 163-166 연속호출 75 위 임 (delegation) 44 열거 46 이스케이프문자 24 이스케이프시권스 25 예외 58 이름 21 연산자우선순위 % 의사 클래스 방식 82 , 예약어 22 , 170 유효범위 28 , 65 , 169 세미콜론 169, 198 스타일 157-162 유니코드 171 86 , 95 I헤 함수호출 패턴 53 메 소드 호출패턴 52 증감 연산자 187. 199. 205 주석 2 1. 161 자바스크립트 분석 표준 new 전치 연산자 14-17 16 리터 럴 50 메 모이 제 이션 78 모률 72 - 75 객 체 49 재귀 호출 62-64 사용해야하는이유 13 재 귀 호출 DOM 63 피보나치 수열 78 DOM 63 꼬리 재귀 최적화 64 하노이의 탑 62 정 규 표현식 111 -129 피 보나치 수열 78 꼬리 재 귀 64 하노이의 탑 62 흩헤 return 밑 apply 호출 패 턴 56 argume nts 57 array, concal() 131 array.jo in () 132 array, po p () 132 array.push () 133 array.reverse() 133 array.shift () 134 array, sli ce() 134 array.sort( ) 135-1 38 array,s plice() 139-1 40 array.lI nshi fl () 141 멜 17 멜 표현식 33-36 ?삼항연 산자 33 이 항연산자 35 호출 35 연산자우선 순위 34 36 변수 33 피 보나치 수열 78 프로토타임 방식 88 핀 멜 R bre잉〈 문 합수호출패틴 53 VeryPDF함수 Demo 객체 47 함수 문장 VS 함수 표현식 188 함수를 사용한 방식(상속) 90-95 함수 인수 배 열 57 기본 타입 에 기 능 추가 59 콜백 기 연속호출 75 콜로저 66-70 커링 76 에외 58 모률 58 m 콜백 70 캐 스팅 81 클로지 66-70 세 부지정 문 유효범 위 65 호출연 산자 34. 52 하노 이 탑 61 철도다이어 그 램 19 테 스트환경 54 호출연산자 52 생성자로 호출 54 72 호출 51-56 apply 호출 패턴 56 생성 자 호출패턴 54 29 , 31 case 절 29 catch 절 31 consU'lI ctor 속성 82 conunue 문 185 curry 메 소드 77 m deentityify 메소드 72 delete 연산자 103 do 문 27 , 30 DOM 63 렘 ECMAScript 언어 명세 194 eval 함수 184 보안 문제점 227 기 아 보 찬 < 239 afor in 30 껴체 46 for 문 27 , 29 function.apply( ) 메소드 141 문 m hasOwnProperty 메소드 45 , 178 , 179 HTML <scrψt ) 태그 (JSON) 225 innerHTML 속성 228 ]SLint 193 I 11 ]SON 15, 223 , 236 /문자 225 배열 225 eva! 함수 227 HTML <script) 태 그 226 innerHTML 속성 228 ]SLin t 193 숫자 226 객체 224 문자열 225 예제 226 안전하게사용 227 ]SON.parse 메소드 228 ]SLin t 16, 193-209 11 parselnt 함수 173 pnvate 메소드 91 prototype 속성 82 m RegExp 껴체 145 regexp.exed ) method 145 regexp.test( ) 메소드 147 return 문 31, 58 setlnterval 함수 184 setTimeout 함수 184 splice 메소드 103 string.charAt() 148 string.charCodeAt( ) 149 string.concat() 149 String .fromCharCode() 156 string .indexOf() 149 string .IastlndexOf() 149 string .I ocaleCornpare () 150 string.match() 150 string.replace() 151 string.search() 153 string.slice() 153 string.split() 154 string.subst:r ing() 155 string.toLoc a! eLowerCase() 155 string.toLocaleUpperCase() 155 string.toLowerCase() 156 string.toUpperCase() 156 then 블록 28 31 σnn 메 소드 60 try 문 31 TypeError 에외 42 typeof 연산자 34 , 104, 171 , 176 throw 문 ( 배열 ) 101 m Math 객체 24 method 메소 드 85 멘 m unde삐ed NaN 22 , 24 , 28 , 33 , 174 new 연산자 사용을 잊은경우 86 함수 54 nulJ 28 , 33 , 177 Objec t. create 메소드 4 1. 44. 108 m var 26 void 연산자 191 m m Z4 0 liI 11 160 VeryPDF11Demo length 속성 메소드 I를 κ 문 28 lnfmity 24 , 33 inherits 메소드 85 mne r대M 속성 228 K&R 스타일 Object.hasOwnProperty( ) Object.prototype 106 90 , 107 while 문 27 , 29 with 문 182 144