비록 현재 왕성한 액션 히어로의 역할로 웹의 커다란 한 부분을 담당하고 있는 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를 한번 돌려 본 사람이라면 많은 골칫거리를 떠안게 된다. 하지만, 대부분의 골 때리는 일들은 잘못된 습관에서 비롯되는 경우가 많으므로 평소에 많은 코드를 접하면서 좋은 습관을 들이도록 노력하는 것이 중요할 것이다.

dLite 로고근래에 다양해진 여러 JavaScript 라이브러리 출현으로 웹 개발 작업에서의 그 사용 빈도는 덩달아서 크게 늘어났으며, 많은 개발자들의 이런 라이브러리들에 대한 의존도 역시 자연 더 높아질 전망이다.
하지만, 이런 만능 JavaScript 라이브러리들을 쓰면서도 정작 특정 프로젝트에 필요한 기능들은 제한적일 수 밖에 없다. 결국, 이런 작업에 이런 덩치 큰 JavaScript 라이브러리의 힘을 빌리는 것은 어쩌면, 과유 불급, 과잉을 자초하는 행위일지도. 그래서, 평상시 개발에 있어서 꼭 필요한 기능들만 모아놓은 알짜배기 JavaScript 라이브러리의 필요성이 대두되었고, 이런 요구에 부응해서 태어난 놈이 이 dLite라는 놈이다.

dLite에 있는 이 알짜배기 기능들을 모두 나열해 보아도 무척이나 단출하다:

  • elm – 특정 id를 포함하고 있는 element 찾기
  • elmsByClass – 특정 class 이름을 포함하고 있는 모든 element들 찾기
  • DOMReadyDOM이 준비가 되자마자 원하는 함수를 실행
  • addClass – class 이름 추가
  • removeClass – class 이름 제거
  • addEvent – 이벤트 핸들러(handler) 추가
  • removeEvent – 이벤트 핸들러(handler) 삭제
  • stopDefault – 이벤트에 부여된 기본 동작이 진행되는 것을 막음
  • cancelBubbling – 이벤트의 버블링(bubbling) 현상을 취소시킴

그야말로, 평상시 자주 쓰이는 알짜배기 함수들만 모아 놓았다.
특히나 모든 dLite 함수들은 global scope에서 정의되어 있기 때문에, objectName.methodName 형식으로 부를 필요없이 함수 이름을 그대로 사용할 수 있다. 물론, 같은 이름의 함수가 이미 존재할 경우에는 원래의 함수가 대신 사용되고, dLite.함수_이름 형태로 dLite에 있는 함수를 끄집어 사용할 수도 있다.

원 개발자의 기존 JavaScript 라이브러리인 DOMAssistant도 상당히 가볍고 좋았는데, 이놈은 그 보다 더 가벼운 DOMAssistant light 정도로 생각된다.

쉽게 빠지기 쉬운 여러 JavaScript 라이브러리들에 대한 깊은 의존도에서 벗어나서 DOM Scripting 기본에 충실하려는 사용자들에게 상당한 매력이 있을 듯.

jQuery UI jQuery UI가 버전 1.5로 갱신되었다. 거의 다시 태어났다고 말하고 싶은 것은 단순한 기능 추가 뿐만이 아니라 기본적인 구조와 사용 용법에 많은 변화가 있었기 때문.

대략적인 주요 내용을 보면, API 사용 용법이 단순화되었고, 다른 파일들과의 의존성을 줄이기 위해 과거 plugin 형태로 있던 dimensions.js가 1.2.6 버전부터 jQuery core에 흡수되었으며, 새로운 ui.core.js가 소개되면서 새로운 plugin을 추가하는 작업이 훨씬 간단해 졌다.

그리고, 원래 Prototype 라이브러리script.aculo.us에 대응하는 프로젝트로 시작된 “Enchant”가 아예 jQuery UI에 합쳐지면서 여러 UI 요소들을 위한 16 가지 이상의 다양한 특수 효과들도 $('div').effect() 형태로 기본적으로 제공된다. 특히나 transfer, explode. clip, scale 효과는 이번에 처음 소개된 것들.

또, 흥미를 끄는 것이 복잡한 형태의 easing 효과들과 Class transitions가 추가되었는데, 특히나 Class transitions는 일종의 morphing 효과를 줄 수가 있어서 CSS의 class에 정의되어 있는 속성으로 점진적으로 바뀌어가는 모습을 보여줄 수가 있다. 이는 최근 Safari에 소개된 -webkit-transition 속성과도 닮아있다.

그리고 이것은 디자이너에게도 반가운 소식일텐데, 새로 만든 UI widget들을 사용하려는 사이트와 잘 어울리는 테마로 꾸며줄 수 있는 ThemeRoller의 소개.

ThemeRoller의 UI 모습
여기서는 각 control들의 색상과 모양을 선택해서 실제 모양을 확인해 본 후, 자기만의 테마를 입힌 UI widget들을 CSS 파일과 데모 페이지가 포함된 ZIP 파일로 내려받을 수 있다. 또, Theme Gallery도 제공하니, 다양한 테마들도 더불어 엿볼 수 있을 듯.

이번 발표 소식을 듣고있자니, 과연 Web UI widget들의 전성시대도 멀지 않았군. jQuery UI Changelog

지금의 웹 어플리케이션 개발의 추이를 보면, 어떤 동작을 부여하는데 있어서 대부분은 특정 DOM elements를 불러와서 원하는 동작 적용하게 된다. 여기서 특정 DOM elements를 가져오는데 걸리는 시간은 웹 어플리케이션의 동작 속도에 커다란 영향을 끼칠 수도 있다.

현재, 많은 JavaScript library들이 CSS3 selectors를 이용해서 특정 DOM 요소들을 불러오는 기능을 구현하고 있으나, 경쟁적인 속도 단축 노력에도 불구하고, 웹 브라우저가 직접 이런 작업을 지원해 준다면 속도와 효율면에서 커다란 득을 볼 수 있는 것은 당연한 얘기다. 이런 작업의 표준화를 위해 W3C에서는 Selectors API를 제공하고 있는데, 마침 얼마전 WebKit에서도 getElementsByClassName을 지원하기 시작한데 이어서, 이제 특정 DOM 요소들을 끄집어 오는 작업을 위한 querySelector와 guerySelectorAll methods를 지원하기 시작했단다.

사용 예를 보면,

/*
   * Get all the elements with class "hot" (duplicating getElementsByClassName)
   * A common use for this is as a toggle;
   * for example, a search feature might tag results with a class
   */
  document.querySelectorAll(".hot");
 
  /*
   * Get the currently hovered element
   */
  document.querySelector(":hover");
 
  /*
   * Get every other element in the <li> with id "large"
   * This is mostly useful for doing "zebra stripe" alternating rows.
   * Once CSS3 becomes more widespread, doing this directly via CSS will be more practical
   */
  document.querySelectorAll("#large:nth-child(even)");

이제, CSS3 selectors를 이용해서 특정 DOM elements를 손쉬우면서도 빠르게 끄집어 내서 동작을 부여할 수 있게 된 것이다. 앞으로 이 Selectors API가 기타 다른 브라우저들에서도 지원해 준다면, DOM Scripting의 효율도 더 높아질 듯 하다.

조만간 있을 Safari의 갱신 때 이것도 포함되었으면 좋겠군.

using a minifed version of the code is much faster than the packed one – even though its file size is quite larger.

JavaScript Library Loading Speed

The iPhone cache experiment suggests an additional performance rule specific for developing web sites for the iPhone: Reduce the size of each component to 25 Kbytes or less for optimal caching behavior.

Performance Research, Part 5: iPhone Cacheability – Making it Stick

잘게 자르는 것도 요령이 필요하군.