아래 코드를 이해하려면 JavaScript 만의 특성이 가미된 scope과 closures 이해하고 있어야 한다.

function add (x) {
  return function (y) {
    return x + y;
  };
}
var add5 = add(5);
var no8 = add5(3);
alert(no8); // Returns 8 

JavaScript를 좀 더 깊게 이해하고 좋은 코드를 짜기 위해서는 꼭 알고 있어야 할 부분이지만, 처음 접하는 사람들에겐 난해하기 마련인데, 마침 Robert씨가 알기 쉽게 풀어서 설명해 놓은 글을 올려놓았다.

더불어서, 위 소개 글에서도 잘 설명되어 있는 JavaScript Module Pattern을 약간 변형시킨 것으로, 스크립트 사용 용법이 좀 더 일관되고 패턴 속의 어떤 함수와 변수가 공개적으로 접근 가능한지를 훨씬 명확하게 보여주는 Revealing Module Pattern도 참고할 만하다. 이 패턴은 원한다면 실제 private 함수를 좀 더 명확한 이름을 지정해 놓고 공개해서 되돌려줄 수도 있는 장점이 있다.

얼마전 Google이 새로운 웹 브라우저 Chrome을 발표하면서, 많은 이들의 관심을 모았었는데, 그 중 Google Chrome 브라우저에 내장된 JavaScript 엔진인 V8의 월등한 성능에 많은 찬사가 이어졌었다.

이에 대한 반격인가? 방금 전 Safari의 WebKit 팀에서도 신형 JavaScript 엔진인 SquirrelFish의 개량형인 SquirrelFish Extreme을 소개하였다.

예전 SquirrelFish 엔진보다 무려 두 배 이상의 성능 향상이 있었다고 하는데, 당장 WebKit Nightly 버전을 받아서 SunSpider JavaScript 성능 테스트를 돌려본 결과 현 Safari 3.1버전보다 거의 세 배 이상의 성능을 보여주고 있다. 이 수치는 최신 V8 엔진보다 SquirrelFish Extreme이 36% 빠른 결과라고.

WebKit Nightlies의 신형 JavaScript 엔진인 SquirrelFish Extreme의 성능을 나타내는 도표로, WebKit 3.1보다 세 배 이상, 이전 SquirrelFish 엔진보다는 두 배 이상의 성능을 보여주고 있다.

이 쯤 되면, TraceMonkey의 분발도 지켜봐야겠군. 😀

그림 파일을 압축하는데 요긴한 종합 선물 세트라고 해야하나. ImageOptim은 맥용으로 나온 꽤 쓸만한 PNG와 JPEG 그림 파일 압축 도구이다. ImageOptim은 모두 다섯 가지의 압축 도구들(AdvPNG, OptiPNG, PngCrush, JpegOptim, PNGOUT)을 내장하고 있어서, 환경설정에서 각 도구들만의 압축 설정이 가능하다.
ImageOptim의 환경 설정 창
저작권 관계로 PNGOUT 바이너리는 직접 내려받아서 적당한 위치에 저장하고, ImageOptim의 환경 설정 창에서 바이너리의 경로를 따로 지정해서 사용해야 한다. 그리고 PNGOUT을 쓰게되면, PngCrush는 기능상 중복되는 부분이 있어서 기능을 꺼줘도 됨.

덧붙임(2012년 3월 5일): 1.4 버전부턴 PNGOUT이 기본적으로 포함되었다.

문득 구독 feed들을 훑어보다가 CSS Opacity에 관한 불길한 내용을 읽게되어 여기에 옮겨놓는다.

CSS 3 Working Draft에 정의되어 있는 Opacity는 그 용법이 명확해서, 대부분의 웹 브라우저들에서 다음과 같이 사용될 수 있다.

#some-div {
  background: #999;
  opacity: 0.5;
  filter:alpha(opacity=50);  /* For IE 5-7 */
}

헌데, IE 8부터 사용하게 될 MS 전용 확장자(-ms-) 덕분에, 상황은 더 복잡해졌다.

IE8가 표준 모드로 웹 문서를 해석할 경우, 과거 MS만의 filter 용법은 완전 무시되면서 -ms-filter 속성과 함께 filter 정의 부분은 따옴표로 감싸주어야만 한다. 그래서, 간단한 opacity 속성 하나를 정의하려고 해도 다음과 같이 지저분한 용법이 사용될 판이다.

#some-div {
  background: #999;
  opacity: 0.5;
  filter:alpha(opacity=50);       /* For IE 5-7 */
  -ms-filter:"alpha(opacity=50)"; /* For IE 8 */
}

쉬운길 놔두고 멀리 돌아가는 것처럼 생각되는데, 이쯤되면 차라리 속편하게 PNG 그림으로 대체하게 생겼군. 하지만, 투명도가 들어간 PNG도 문제가 많으니 이래저래 골칫거리. 😐
결국, IEBlog에 나와 있는 대로 두 줄로 요약된다.

.fiftyPercentOpaque {
  opacity: 0.5; /* All modern browsers including IE9 */
  filter: alpha(opacity=50); /* IE5-IE9 */
}

내용 갱신: IE9을 포함한 모든 브라우저를 위한 Opacity 설정 방법.

.transparent {
  zoom: 1;
  filter: alpha(opacity=50);
  opacity: 0.5;
}

비록 현재 왕성한 액션 히어로의 역할로 웹의 커다란 한 부분을 담당하고 있는 JavaScript라도 그 결점은 있기 마련이고, 언젠가는 이러한 언어 설계상의 오류가 자기의 뒤통수를 때릴 때가 있을 것이다. 결국, 미리 알아서 조심해야지.

JavaScript에서 NaN 값은 not a number라는 뜻으로, 즉 숫자가 아니라는 의미이다. 하지만,

typeof NaN === 'number' // true 

이렇듯, typeof로는 NaN와 숫자를 구분할 수가 없거니와, 자신과의 비교도 불허한다.

NaN === NaN    // false 
NaN !== NaN    // true 

결국, JavaScript에서는 숫자와 NaN를 구분하는 isNaN라는 함수를 제공하고 있다:

isNaN(NaN)       // true 
isNaN(0)         // false 
isNaN('oops')    // true 
isNaN('0')       // false 

결국, 숫자를 구별하는 가장 확실한 방법으로 다음과 같은 함수가 쓰일 수 있겠다:

function isNumber(value) {
  return typeof value === 'number' && isFinite(value);
}

typeof 얘기가 나와서 그러는데,

typeof null     // object 

null 대신에 object를 돌려받는다. 그래서, null 값을 알아보기 위한 가장 좋은 방법은 아래와 같다:

my_value === null

또한, JavaScript의 Reserved Words는 보통 변수 이름으로 사용될 수 없는데, 굳이 reserved words를 object literals의 키 값으로 사용하려 할 경우에는, 항상 따옴표도 함께 써줘야 하고 dot notation 대신에 bracket notation을 사용해야 한다:

var method;                // ok 
var class;                 // illegal 
object = {box: value};     // ok 
object = {case: value};    // illegal 
object = {'case': value};  // ok 
object.box = value;        // ok 
object.case = value;       // illegal 
object['case'] = value;    // ok 

JavaScript는 프로그램 상 오류를 자동 수정하려는 성질이 있어서 문단 마지막에 항상 semicolons을 삽입하는데, 이것이 오히려 아래처럼 뜻하지 않는 문제를 일으킬 수도 있다.

return
{
  status: true
};

return 뒤에 바로 semicolon이 붙어버리면서 결국, undefined 값을 돌려주게 된다. 그래서 { 는 항상 아래처럼 앞 줄의 맨 마지막에 붙여주는 스타일을 손에 익혀야 한다.

return {
  status: true
};

그리고 string을 integer로 바꾸어주는 parseInt 함수를 사용할 때는 항상 radix 매개 변수를 사용하는 버릇을 들여서, 아래와 같이 뜻하지 않는 결과를 초래하는 일을 미연에 방지한다.

parseInt("08");      // 0  
parseInt("09");      // 0 
parseInt("08", 10);  // 8 

또 하나, JavaScript의 소수점 계산은 형편없는 것으로 악명높다:

alert(0.1 + 0.2); // 0.30000000000000004 

이것은 JavaScript만의 문제가 아니라, Binary Floating-Point Arithmetic(IEEE 754)을 채용한 언어들에서 공통적으로 나타나는 문제점으로, ECMAScript 4에서는 Real Decimals의 채용하면서 이를 극복할 수 있는 문제지만, 당분간은 미리 scaling 해서 이 문제를 피할 수 밖에.

다음은 JavaScript에서 사용되는 여러가지 “falsy” 값들이다:
0(Number), NaN(Number), ”(String), false(Boolean), null(Object), undefined(Undefined).

모두 “falsy” 값을 가지지만 번갈아 서로 혼용되서 사용될 수는 없어서, 예를 들어 null 값을 구하는데, undefined를 대신 사용하면 잘 못된 결과를 얻게 된다. 이 얘기는 자동 타입 변환(type coercion)을 일으키는 == 연산자 대신에 더 염격한 === 연산자를 사용하라는 얘기와 맞닿아 있다.

이 외에도, 실수든 혹은 필요에 의해서든 상호 운용성을 떨어뜨리는 global variables의 남용 등, JavaScript 문법 검사기인 JSLint를 한번 돌려 본 사람이라면 많은 골칫거리를 떠안게 된다. 하지만, 대부분의 골 때리는 일들은 잘못된 습관에서 비롯되는 경우가 많으므로 평소에 많은 코드를 접하면서 좋은 습관을 들이도록 노력하는 것이 중요할 것이다.