티스토리 뷰
원래 발표 자료는 총 15장이 었는데, 예제 코드와 설명이 필요한 것은 이번으로 마무리 하려고 한다.
자바스크립트는 약한 타입(weak typing) 이므로, 묵시적인 형변환(implicit type conversion)이 빈번하게 이루어진다. 이로 인한 부작용을 간과하면 찾기 어려운 버그를 만들 수 있다.
간단한 예를 통해 알아보자:
function test(foo) { alert(typeof(foo)); alert(foo); if (foo) { alert('foo'); } if (foo == null) { alert('foo == null'); } if (foo === null) { alert('foo === null'); } }
이 함수를 여러가지 파라메터를 주면서 호출해보자.
test(); test(null); test('hello'); test(''); test(true); test(false); test(1); test(1/0); test(0/0);
특이한 것 몇가지만 얘기하면:
- underfined는 == null 이지만 === null 은 아니다.
- ''는 false다! (C에서는 !=0 이면 모두 true라는 사실을 기억하라)
- 1/0(불능)은 true지만, 0/0(부정)은 false다!
묵시적 형변환과 관련된 또 다른 예를 살펴보자:
function test(foo) { alert(typeof(foo)); alert(foo); if (foo) { alert('foo'); } if (!foo) { alert('!foo'); } if (!!foo) { alert('!!foo'); } }
파라메터가 명확한 불린 값이라면(true/false) 아무런 문제가 없지만, 그렇지 못하면 예상치 못한 상황에 직면하게 된다:
test(true); test(false); test('true'); test('false');
특이한 것은:
- !!'false'는 false가 아니라 true다.
weak typing은 아주 편리한 언어적 특성이지만, 잘못쓰면 - 특히 strong typing(C, 자바 등의 대부분의 주류 언어)에 익숙한 개발자들에게 - 치명적인 독이 될 수 있다. underfined, null, NaN 그리고 ""(빈문자열) 간의 차이는 상당히 오묘하므로, 가장 확실한 방법은 확신이 없다면 명시적인 형변환을 수행하는 것이다.
nested block scope
function test() { var foo = -1; for (var foo = 0; foo < 10; foo++) { … } alert(foo); }
위의 코드에서 두번째 var 선언문은 아무 효과가 없다. 따라서, -1이 아니라 10이 출력된다. 별것 아닌것 처럼 보이지만, 문제가 되면 굉장히 찾기 어려운 버그다. jslint를 사용하면 경고를 해주는 데, 가장 확실한 방법은 모든 변수 선언을 함수 앞에 모아두는 것이다(예전 C 스타일).
function overloading
function test(foo) { alert('one arg'); } function test(foo, bar) { alert('two args'); } function test() { for (var i = 0; i < arguments.length; i++) { alert(arguments[i]); } }
위의 코드에서 앞에 두개의 함수 정의는 무시되고, 마지막의 세번째 함수 정의만 유효하다. 자바스크립트에서는 arguments를 사용하여 가변 파라메터를 처리할 수 있다. 그러나, 더 좋은 방법은 이름있는 파라메터를 사용하는 것이다. 즉, 객체 하나에 파라메터의 이름과 값을 함께 전달 하는 것인데, 요즘 많이 쓰이는 대부분의 자바스크립트 라이브러리들이 모두 이 방식을 선호한다.
"string" is not array-of-chars
var str = "hello"; alert(str.charAt(2)); alert(str[2]);
위의 코드에서 앞의 alert은 출력되지만, 뒤의 alert은 에러다. 잘된다고? IE에서는 해보시길...
자바 개발자들에겐 익숙할텐데, C/C++ 개발자들은 좀 귀찮을 듯... ^^;
비슷한 예로, NodeList(예: document.getElementsByName() 등의 리턴 형식)도 배열이 아니다.
missing "radix" for parseInt()
parseInt('1234'); parseInt('01234'); parseInt('0x1234'); parseInt('1234', 10); parseInt('1234', 8); parseInt('1234', 16);
뭐가 이상하냐고? 자바에서 똑같은 짓을 해보자. -.-;;;; 자바에선 Integer.parseInt()에 radix를 지정하지 않으면 10을 지정한 것으로 처리하지만, 자바스크립트에선 알아서 하라는 뜻으로 해석한다.
var sum = parseInt(num1.value) + parseInt(num2.value); alert(sum);
위의 코드는 의도했던 안했던, 8진수와 16진수 계산기 기능도 갖고 있다. ^^; 이런 사소한 문제가 찾아내기 힘든 버그를 만든다. jslint를 사용하면 경고를 해주는데, 가장 확실한 방법은 parseInt()를 호출할 때 무조건 두번째 파라메터(radix)를 지정하는 것이다.
이것으로 JavaScript Common Mistakes 시리즈도 끝~
그 시작은 창대하였으나 끝은 미미하리라...=3=3=333
'hacking > web' 카테고리의 다른 글
HTML5/CSS/JavaScript로 아이폰 "앱" 만들기 (6) | 2010.11.14 |
---|---|
Jo HTML5 Mobile Application Framework 초간단 리뷰 (0) | 2010.10.08 |
JavaScript Common Mistakes(2) - This "this" is not the "this" (2) | 2009.12.09 |
JavaScript Common Mistakes (1) - Async! Async! Async! (10) | 2009.12.08 |
dwLive! 웹개발 다반사 - 발표 자료(JavaScript Common Mistakes) + 후기 (4) | 2009.12.05 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- Eclipse
- ***1/2
- nodejs
- ***
- 땅끝마을
- DeveloperWorks
- 장필순
- ****
- 노래
- **
- webapp
- 책
- 영화
- 여행
- CSS
- Prototype
- Java
- jQuery
- 독후감
- web
- docker
- Dojo
- 자바스크립트
- 해남
- 자전거
- JavaScript
- maven
- HTML5
- Ajax
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함