본문 바로가기
javascript

[Javascript] 스코프, 호이스팅(Hoisting)

by dyyoo 2019. 10. 21.

평소에 대충 알던, 정확히 설명을 못하는 주제들이 많다고 느껴서 개념부터 공부를 시작했다.

 

설명을 못하면 모르는 거다.

 

 

 

 

[스코프]

- 변수의 유효 범위.

- 블록 스코프는 중괄호{}로 감싸진 범위

  ->if, for, function의 {}

- 함수 스코프는 function의 {} 범위

 

RHS, LHS 검색을 알면 이해하기 쉽다. (https://endus0713.tistory.com/17)

 

- ES6의 let, const는 블록 스코프에서 유효하다.

- var는 함수 스코프에서 유효하다.

 

-----------------------------------------------------------------------------------------

var / let, const의 차이

차이를 공부하다보니, 호이스팅을 알아야 했다.

 

 

호이스팅이란 선언문을 유효범위의 최상단으로 올리는 것.

/* 
[Javascript] Hoisting
*/
function hoisting() {
    if (true) {
        var hVar1 = "aaa";
    }
    console.log(hVar1);

    h1();
    function h1() {
        var hVar2 = "bbb";
        console.log("ccc");
    }
}
//hoisting()이 호이스팅되면 hoisting2()
function hoisting2() {
    var hVar1; //선언문이 유효범위(hoisting2()내의 최상단으로)
    function h1() { //함수 '선언'도 최상단으로
        var hVar2; //h1() 내부 최상단
        hVar2 = "bbb"; //hVar2 할당
        console.log("ccc");
    }
    
    if (true) {
        hVar1 = "aaa"; //hVar1 할당
    }
    console.log(hVar1);
    h1();
}

위의 hoisting()이 hoisting되면 hosting2()와 같다.

 

그렇다면 변수와 함수의 호이스팅 우선순위는 어떨까?

결론부터 말하면,

     1. 변수 '할당' > 함수 선언 > 변수 선언 

 

 함수 선언문과 변수 할당문이 존재하면, 아래 순서로 실행된다.

     1. myName 변수 선언 

     2. myName 함수 선언 

     3. myName에 string 값 할당.

//변수, 함수의 호이스팅 우선순위
function hoisting3() {
    var myName = "myName is String";

    function myName() {
        console.log("myName function");
    }
    function yourName() {
        console.log("yourName function");
    }

    var yourName = "yourName is String";

    console.log(typeof myName); //string
    console.log(typeof yourName); //string
}

위 코드를 단순하게 보면, myName에 string이 할당된 후에, function으로 할당 되었다.

하지만 호이스팅되면 아래 코드와 같이 실행된다.

//hoisting3()이 호이스팅되면 hoisting4()
function hoisting3() {
    var myName;
    var yourName;

    function myName() {
        console.log("myName function");
    }
    function yourName() {
        console.log("yourName function");
    }

    myName = "myName is String";
    yourName = "yourName is String";
    
    console.log(typeof myName); //string
    console.log(typeof yourName); //string
}

 

-----------------------------------------------------------------------------------------

 

다시 var / let, const의 차이로 돌아오면

* let, const는 블록 스코프 내에서 동작한다. 

* 호이스팅 또한 일어난다.

   -> 다만 초기화 되기 전까지 temporal dead zone 이라는 곳에 머문다.

       -> temporal dead zone 은 변수가 초기화되기 전에 할당되어 참조 불가능하다.

 

 

아래 코드를 보면, let의 경우, letConst() 블록 내에서 유효하고,

블록 안의 console.log(b)는 20을 출력하지 못했다.

 

letConst2()를 보면, 블록 안의 let b는 선언되었지만, 참조 할 수없기 때문에, 

밑의 console.log에서 undefined가 아닌 b is not defined error가 발생한다.

그리고 최 하단의 console.log(b)의 경우, 블록 내의 b가 아닌, letConst 함수 스코프내의 b를 RHS검색해 20을 출력한다.

/* 
[Javascript] Let, Const
*/
function letConst() {
    let a = 10;
    let b = 20;

    {
        console.log(a); //10
    }

    {
        console.log(b); // b is not defined
        let b = 30;
        console.log(b); // 30
    }
    console.log(b); // 20
}
//letConst()이 호이스팅되면 letConst2()
function letConst2() {
    let a;
    let b;
    a = 10;
    b = 20;

    {
        console.log(a); //10
    }

    {
        let b; // 호이스팅되었지만, temporal dead zone에 있기 때문에, 참조할 수 없다.
        console.log(b); // b is not defined
        b = 30; //할당
        console.log(b); // 30
    }
    console.log(b); // 20
}

 

 

여기까지.

스코프, 호이스팅을 공부했는데, 뭔가 뒤죽박죽이지만 머리속에는 정리가 된 느낌이다.

 

 

 

'javascript' 카테고리의 다른 글

[Javascript] 1급 객체(First-class object)  (0) 2019.11.06
[Javascript] Closure  (0) 2019.10.22
[Javascript] LHS,RHS 검색  (0) 2019.10.21
javascript에서 replace all 구현  (0) 2019.04.25
함수 표현식, 함수 선언식  (0) 2019.04.25

댓글