본문 바로가기

JavaScript

자바스크립트 코딩 기법과 핵심 패턴 : 2장 기초

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

요즘 개인적으로 자바스크립트를 공부하고 있다. 하지만 내 경우 어정쩡하게 알고 있는 자바스크립트라 기초책은 보나마나인데, 이 책은 정말 실무에서도 바로 쓸 수 있는 패턴을 뽑아서 먹여주는 책 같다. 이 책과 더불어 자바스크립트 성능 최적화도 보면 정말 좋겠다. 아무튼 이 책을 요약하면서 정리하고자 한다. 이 책은 정말 강력 추천하며 자바스크립트를 제대로 학습하기 위한 필수 소장서이다.

책구입 : http://tinyurl.com/7ejd4rs
출판사 책소개 : http://blog.insightbook.co.kr/245


자바스크립트 코딩기법과 핵심패턴 제 2장 기초 정리


유지보수 가능한 코드 작성


유지보수가 가능한 코드란 다음과 같은 특징을 가짐
  • 읽기 쉽다.
  • 일관적이다.
  • 예측 가능하다.
  • 한 사람이 작성한 것처럼 보인다.
  • 문서화되어 있다.

전역변수를 최소화 하라!


전역변수는 자바스크립트 애플리케이션이나 웹페이지 모든 코드 사이에서 공유된다는 문제점이 있다.
그러므로 전역변수는 최소한으로 사용한다.
1.myglobal = "hello"; //안티패턴
2.console.log(myglobal); //hello
3.console.log(this.myglobal); //hello
4.console.log(window.myglobal); //hello
5.console.log(window["myglobal"]); //hello

암묵적 전역(implied globals)
암묵적 전역은 절대적으로 피하는 것이 좋다. 아래 예도 그렇지만 다른 이유로 이식성(portability) 때문. 암묵적 전역 변수가 새로운 실행환경에서 호스트 객체를 의도치 않게 덮어쓸 수 있기 때문.
01.function sum(x, y) {
02.   result = x + y; //안티패턴 - 전역 네임스페이스에 result 변수가 남게된다.
03.   return result;
04.}
05.function sum(x, y) {
06.   var result = x + y; //추천패턴 - 언제나 var을 사용해 변수를 선언해야 한다. 이때 result는 지역변수가 된다.
07.   return result;
08.}
09.function foo() {
10.   var a = b = 0; //안티패턴 - 이것은 var a = (b = 0); 과 같다. 즉 b가 암묵적 전역이 된다.
11.}
12.function foo() {
13.   var a, b;
14.   a = b = 0; //추천패턴 - 이 경우 모두 지역변수가 된다.
15.}

단일 var 패턴을 사용하라


아래처럼 사용하는 패턴이 좋다. 장점은 변수 찾기 용이(명시적)이며, 로직상 오류를 방지(예를 들어 호이스팅)한다. 또한 의도적이지 않은 전역 변수 사용을 최소화할 수 있다. 뿐만아니라 코드링이 줄어든다.
01.function func() {
02.   var a = 1,
03.       b = 2,
04.       sum = a + b,
05.       myobject = {},
06.       el = document.getElementById("result"),
07.       style = el.style
08.       i,
09.       j;
10.}

호이스팅(hoisting)


호이스팅(끌어올리기)은 함수내에 어디서든 var 선언을 사용하더라도 함수 상단에 선언한 것과 동일한 동작을 하는 방식을 말함. 중요한 것은 선언만 호이스팅되는 것이지... 정의는 호이스팅 되지 않는다.

for 루프


다음처럼은 절대 쓰지 않는다.
1.for(var i = 0; i < myArray.length; i++) {
2.   //myarray[i]를 다루는 코드
3.}

다음 처럼 쓴다.
1.for(var i = 0, max = myarray.length; i < max; i++) {
2.   //myarray[i]를 다루는 코드
3.}

for내에 var 선언은 단일 var 패턴을 해도 된다.
i++대신 i = 1을 사용하는 것이 좋다. +, --는 과도한 기교를 조장한다는 이유이다.

미세 최적화를 위해 두가지 패턴을 활용한다.
  • 변수를 하나 덜 쓴다.
  • 카운트를 거꾸로 0으로 내려간다. 0과 비교하는 것이 0이 아닌 값으로 비교하는 것보다 빠르기 때문.

for-in 루프


for-in으로 루프를 도는 것을 열거(enumeration)라고 한다. 이 루프는 반드시 배열이 아닌 객체를 순회할 때만 사용한다.

프로토타입 프로퍼티만을 걸러내기 위해 hasOwnProperty() 메서드를 사용한다.
1.for(var i in man) {
2.    if(man.hasOwnProperty(i)) {
3.      console.log(i, ":", man[i]);
4.    }
5.}

다음처럼 해도 된다. 이 방법은 man객체가 hasOwnProperty를 재정의하여 덮어써도 활용할 수 있다.
1.var i,
2.    hasOwn = Object.prototype.hasOwnProperty;
3.for(i in man) {
4.    if(hasOwn.call(m, i)) {
5.      console.log(i, ":", man[i]);
6.    }
7.}

내장 생성자 프로토타입은 되도록 확장하지 말자.
생성자 함수의 prototype 프로퍼티를 확장하는 것은 기능을 추가하는 좋은 방법이나 너무 강력함. 그러므로 Object(), Array(), Function()과 같은 내장 생성자의 프로토타입을 확장하는 것은 매력적이나 코드의 지속성을 심각하게 저해할 수 있다. 하지만 무조건 나쁘지만은 않으므로 꼭 필요한 경우 정의한다.
1.if (typeof Object.prototype.myMethod !== "function") {
2.   Object.prototype.myMethod = function () {  
3.       // 구현...
4.   };
5.}

switch 패턴


  • case문을 switch문에 맞추어 정렬
  • case문 안에서 코드를 들여쓰기 한다.
  • case문은 명확히 break;로 종료
  • break문을 생략하여 통과시키지 않는다. 필요한 경우 기록을 남긴다.
  • 반드시 default:을 쓴다.
01.switch( inspect_me) {
02.case 0:
03.     result = "zero";
04.     break;
05.case 1:
06.     result = "one";
07.     break;
08.default:
09.     result = "unknown";
10.}

암묵적 캐스팅 피하기


false 0, "" 0 이 모두 true가 되기 때문에
암묵적 캐스팅으로 인한 혼동을 막기 위해 완전항등연산자인 ===, !== 연산자 만을 사용한다.

evel()은 보안문제로 무조건 피하라!


setInterval(), setTimeout(), Function() 생성자에 문자열을 넘기는 것도 eval()처럼 문제가 발생할 수 있으므로 피한다.
1.var property = "name";
2.alert(eval("obj." + property)); //안티패턴
3. 
4.setTimeout("myFunc()", 1000); //안티패턴
5.setTimeout("myFunc(1, 2, 3)", 1000); //안티패턴

만약 eval()을 사용해야하는 경우가 발생한다면 new Function(); 을 고려하자. eval()은 유효범위 체인에 간섭을 일으킬 수 있는 단점이 있는 반해, Function은 좀더 봉인 되어 있다. new Function()과 Function()은 동일하다.

parseInt()를 통한 숫자 변환


문자를 숫자로 바꾸는 방법은 parseInt("05", 10)와 Number("05") 방법이 있다. 단, parseInt의 경우 "05"처럼 앞에 0이 있는 경우에는 반드시 두번째 인자가 10(10진수의 의미)이 되어야 한다. 하지만 Number는 상관없다. Number의 경우 "05 hello"등은 바꿀 수 없고 NaN처리 되지만 parseInt()는 5가 잘 나온다.

코딩규칙


  • 적절한 들여쓰기 사용
  • 중괄호는 생략할 수 있어도 꼭 쓸 것
  • 중괄호 여는 위치는 "세미콜론 삽입 장치" 문제로 반드시 아래처럼 쓰는게 좋다.
    1.function func() {
    2.  return {
    3.    name: "Batman"
    4.  };
    5.}
  • 공백은 코드가 숨쉴 수 있게하는 요소. 하지만 코드 컨벤션에 따라서 쓰면 되겠다.

명명규칙


  • 생성자는 대문자로 시작
  • 단어 구분에는 낙타표기법(camel case) 사용 - 단 생성자는 대문자 낙타표기법은 함수는 소문자 낙타표기법을 사용한다.
  • 상수는 대문자와 _를 적절히 사용한다.
  • private나 protected는 __myPrivateMethod, _myProtectedMethod 처럼 구분하도록 하자.

주석 작성


YUIDoc(http://yuilibrary.com/projects/yuidoc), JSDoc(http://code.google.com/p/jsdoc-toolkit) 활용

출시단계 압축


야후의 YUICompressor 나 구글의 Closure Compiler 활용.

JSLint 실행


지금까지 다룬 패턴 위반사례를 잡아줌.