Javascript

Effective JavaScript [12] - 변수 호이스팅

weicome 2016. 12. 6. 23:55



본 게시물은 Effective Javascript의 내용을 재구성하여 작성되었음을 알립니다. 저작권 문제 발생시 게시물이 비공개 될 수 있습니다. 



- 블록 내에서의 변수 선언은 암묵적으로 그 변수를 포함하는 함수의 맨 윗부분으로 호이스팅된다.

- 변수의 재선언은 하나의 변수처럼 처리된다.

- 혼란을 막기 위해 지역 변수 선언을 직접 호이스팅하는 것을 고려하라.




자바스크립트는 어휘적 스코프를 지원하지만, 블록 단위 스코프를 지원하지 않는다. 변수 정의는 자신을 포함한 함수에 의해 지정된다. 


function isWinner(player, others) {

    var highest = 0;

    for (var i = 0, n = others.length; i < n; i++ ) {

        var player = others[i];

        if (player.score > highest) {

            highest = player.score;

        }

    }

    return player.score > highest;

}


player를 반복문의 본문 안에서 선언하려는 듯 보인다. 하지만 자바스크립트 변수는 블록이 아닌 함수에 의해 스코프가 정해지기 때문에 player 내부 선언은 이미 스코프안에 선언된 변수 player 파라미터를 재선언 하는 것 뿐이다. 반복문의 이터레이션마다 동일한 변수를 덮어쓰게 된다. 그 결과, return 선언문은 player를 함수의 원래 player 인자가 아닌 마지막 요소로 보게 된다. 


자바스크립트 변수 선언의 동작과 할당의 부분으로 나누어 이해해야 한다. 자바스크립트는 암묵적으로 함수 맨 윗부분으로 선언을 끌어올리고 할당 부분은 그 자리에 그대로 둔다. 변수는 전체 함수의 스코프 안에 있지만 실제로 var 선언문이 나타난 곳에서만 할당되는 것이다. 




호이스팅은 변수를 재선언할 때 혼란을 초래할 수 있다. 동일한 함수 내에서 같은 변수를 여러 번 정의하는 것은 허용되지 않는다. 


function trimSections(header, body, footer) {

    for ( var i = 0, n = header.length; i < n; i++ ) {

        header[i] = header[i].trim();

    }

    for (var i =0, n = body.length; i < n; i++) {

        body[i] = body[i].trim();

    }

    for(var i = 0, n = footer.length; i < n; i++) {

        footer[i] = footer[i].trim();

    }

}


trimSections 함수는 여섯 개의 지역번수(i 3개, n 3개)를 선언하지만 호이스팅으로 오직 2개만 선언되었다. 호이스팅 된 이후에는 trimSections 함수는 다음과 같이 쓰여진 셈이다.



function trimSections(header, body, footer) {

    var i, n;

    for ( i = 0, n = header.length; i < n; i++ ) {
        header[i] = header[i].trim();
    }
    for ( i =0, n = body.length; i < n; i++) {
        body[i] = body[i].trim();
    }
    for( i = 0, n = footer.length; i < n; i++) {
        footer[i] = footer[i].trim();
    }

}


재선언은 별도의 변수를 나타내기 때문에, 모호함을 줄이기 위해 함수의 맨 윗부분에 모든 var 선언문을 위치시키는 방식을 선언한다. 이런 스타일은 마음에 들지 않더라도, 자바스크립트의 스코프 규칙을 이해하는 것은 코드를 읽고 쓰는데 중요하다. 


자바스크립트에서 블록 스코프가 지원되는 예외 상황 중 하나는 바로 exception 이다. try ... catch는 exception을 잡아 변수로 바인딩하고 catch 블록 안에서만 스코프가 적용된다.


function test ( ) {

    var x = "var", result = [ ];

    result.push(x);

    try {

        throw "exception";

    } catch (x) {

        x = "catch";

    }

    result.push(x);

    return result;

}


test ( );    /// ["var", "var"]



- 블록 내에서의 변수 선언은 암묵적으로 그 변수를 포함하는 함수의 맨 윗부분으로 호이스팅된다.

- 변수의 재선언은 하나의 변수처럼 처리된다.

- 혼란을 막기 위해 지역 변수 선언을 직접 호이스팅하는 것을 고려하라.




끄읕.