몇달전 자바스크립트 가든이라는 문서의 한글 번역본을 읽다가 포기하고 다시 원문을 보면서 재번역을 했다. 처음엔 그냥 오역이 몇가지 보여서 오역만 바로 잡아볼까하고 원번역자에게 메일을 보냈는데.. 결국엔 전체를 모두 다시 번역했다. 현재는 원저자에게 Pull Request를 보낸상태고 머지는 언제 될찌 모르겠다. 현재 상황에서 기억 남는 몇가지를 남겨보면,
1. 호이스팅(Hoisting)
이게 말이지 참 재밌다. JSLint에서 이렇게 해라~ 라고 추천했던 가이드들이 몇가지 있었는데.. 예를 들면,
“var문은 맨위로 올려라” 하는 가이드가 있다. 왜 위로 올리라는 거지? 성능 문젠가? 스코핑 때문에 그런가? 그래.. 올리라면 올리지모.. 라고 하면서 var로 선언한 코드를 전부 위로 올렸던 기억이 있는데.. 여기엔 이유가 있었다. 바로 호이스팅!!! 호이스팅은 자바스크립트가 실행되기 전에 선언문을 스코프 위로 올리는 걸 얘기한다. 따라서 다음과 같이 for 문안에 선언한 i 변수는
for(var i=0; i<1000; ++i){ // 어쩌구 저쩌구 }
다음과 같은 스코프 상단으로 옮겨진다는 사실!!
var i=0; for(i=0; i<1000; ++i){ // 어쩌구 저쩌구 }
이렇게 자동으로 옮겨지는 것을 호이스팅이라고 한다. 이런 특징을 모르면 전역변수를 의도하고 쓰더라도 실제 지역변수에 있는 값을 쓰게 될지도 모른다!! 자세한 내용은 자바스크립트 가든의
함수 스코프를 참고하자!
2. 왜 new Array()는 안되는가?
이것도 역시 JSLint에서 가이드하는 내용중에 하나다. new Array()로 쓰지말고 [] 각괄호를 이용해 배열을 선언하라고 하는데, 이유는 new Array(3) 으로 넣을때 우리가 생각했던대로 동작하지 않기 때문이다. 보통은 배열에 3이라는 값을 하나 추가한 결과를 반환해줄꺼라 기대하지만, 요건 배열의 크기가 3인 빈배열을 반환한다. 심지어 인덱스는 초기화도 안한다는 사실!! 역시 자세한 내용은 자바스크립트 가든의
배열 생성자를 참고하자.
3. 계륵 같은 new 키워드의 비밀
함수를 만들때 new 키워드를 붙여서 생성하지만, new 키워드가 없어도 생성할수있다.
function Foo(){ this.value = 1; } new Foo(); Foo();
위와 같이 호출하면 new 키워드의 유무에 따라 반환 값이 달라진다. new 키워드를 붙이면 Foo 함수가 생성자로써 동작하게 되면서 특별한 반환값이 없으면 this가 가리키는 값을 반환해준다. 즉, Foo 객체의 인스턴스를 반환해주는데,. Foo()는 그냥 함수를 실행한다. 그래서 this 객체는 Foo를 가리키는게 아니라 전역을 가리키게 되고, 반환하는 값이 없으므로 결과값은
undefined 가 된다. 뭐 여기까지는 누구나 아는 사실인데.. Foo 객체가 생성자로 동작할때 즉, new 키워드가 붙을때 , 이 생성자에 명시적인 return 값이 있다면 또 얘기가 달라진다. 명시적인 객체를 리턴하면 그값이 결과값으로 반환되지만, return 값이 없거나 참조타입이 아닌 프리미티브 타입을 반환하면 this가 가리키는 값을 반환한다. 반면에 new 키워드가 없는 경우, Foo 객체는 생성자가 아닌 일반 함수로 동작하면서 return 문의 값을 반환한다. 그래서 결론은 명시적인 반환값을 객체로 주면, new 키워드가 있든 말든 동일하게 동작한다는 사실!! 그래서 팩토리 패턴으로 만들 경우 자연히 new 키워드가 필요없게 된다! 자세한 내용은 역시 자바스크립트 가든의 함수 생성자를 참고하자!
4. 타이머는 스택킹 된다!
자바스크립트에서 타이머는 setTimeout과 setInterval 두가지가 있다. 어찌 생각해보면 setIntveral을 한번만 실행하고 없애면 setTimeout 은 필요없는거 아닌가? 하는 생각을 종종했는데.. 역시나 setTimeout은 ECMA 표준 스펙이 아니었다! 헉! 그랬꾸나.. 그래서 setTimeout의 첫번째 인자에 대한 해석도 엔진마다 다르다는 사실!… 여튼 이건 뭐 그렇게 중요한 얘기는 아니고.. 진짜 재밌는 얘기는 바로 setInterval 함수가 스택킹된다는 사실이다! setInterval 함수는 일정 주기마다 함수가 호출되는데.. 엄밀히 말하면 일정주기마다 함수를 실행하는 것은 아니고 일정 주기마다 실행할 함수를 쌓는다. 그래서 자바스크립트 쓰레드가 그 함수를 실행할때가 되면 실행하게 될테고, 뒤이어 실행되어질 함수는 앞에 함수가 다 끝날때까지 기다리게 된다. 이거다 싱글 쓰레드라서 발생하는 문젠데.. 그럼 한번 생각해보자!. 주기가 엄청 짧은데.. 실행되는 함수는 그 주기보다 길경우 어떻게 될까? 그렇다! 무조건 쌓이게 된다!! 이렇게 쌓인 함수는 시간이란 변수가 더이상 필요없게 된다. 즉, 내가 원하는 주기가 깨질수도 있다는 사실!! 자세한 내용은
타이머를 참고하자!
5. 삼중 등호의 비밀
이중 등호(==)와 삼중 등호(===) 지금까지는 삼중 등호는 인스턴스를 비교해서 보다 정확하고, 이중 등호는 대충 (?) 비교해서 부정확하다라고 생각하고 있었다.. 하지만 이 둘의 차이는 그런게 아니었다.!! 바로 자동 타입 변환을 하느냐 마느냐의 차이!! 이중 등호는 자동 타입 변환을 해서 끝까지 비교하지만, 삼중 등호는 타입 변환 없이 바로 비교한다. 그래서 훨씬더 빠르다! 자세한 내용은
타입 비교를 봐라! 이 외에도 재밌는 내용이 참 많은데.. 여튼 난 위 5가지가 가장 새로웠다!