프로그래밍/

[자바스크립트] 스코프, 변수 호이스팅(hoisting), ES6에서의 개선점

Jay Tech 2017. 12. 8. 02:11
반응형

호이스팅 (hoisting)

자바스크립트 (ES5) 에서 변수선언에 있어서 var 키워드는 스코프(scope)의 제일 위로 옮겨져서 선언이 된다. 이것을 호이스팅(hoisting)이라고 한다.


1
2
3
4
5
6
7
function foo() {
    for(var i=0; i<10; i++) {}
 
    console.log(i);
}
 
foo();
cs


결과적으로 i는 10이라는 값이 출력이 된다. i는 확실히 for문안에서 쓰려고 만든 것이지만 for 루프 밖에서도 접근이 가능하다. 이처럼 자바스크립트는 다른 언어와는 달리 일반적인 스코프를 따르지 않는다. 


그럼 자바스크립트에서 스코프를 생성하는 때는 언제일까?


function

with

catch


이 구문들을 사용할 때 스코프가 생성이되고 다른언어들 처럼 {} 중괄호를 썼다고 해서 스코프가 생성되지 않는다.


1
2
3
4
5
function foo() {
    var a = "access?";
}
 
console.log(typeof a === "undefined");
cs



결과는 true이다. a라는 변수는 function foo() 외부에서 접근할 수가 없다. 스코프가 생긴 것이다.



변수선언이 호이스팅 되는 예제


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html>
  <body>
    <script>
      "user strict";
 
      var customer = "Joe";
 
      (function() {
        console.log("inside : " + customer);
 
        // if(2>1) {
        //   var customer = "Mary";
        // }
      })();
 
      console.log("outside : "  + customer);
    </script>
  </body>
</html>
cs



주석 처리를 한 상태에서는 customer는 전역 변수이므로 출력결과가 둘다 Joe 가 된다.


하지만 주석을 해제하면 function 안의 customer는 undefined가 된다.


ES5에서는 변수 선언이 선언 범위의 제일 위로 올라가게 된다. 즉 저 function 안에서 customer는 제일 위로 올라가서 선언 자체는 된다. 하지만! 초기화는 그 장소에서 초기화가 된다. 다시 말해서 변수 선언은 호이스팅(hoisting)이 되지만 초기화는 호이스팅이 되지 않는다.


그래서 주석 처리를 해제한다면 콘솔에서 찍는 customer는 초기화가 되어있지 않으므로 undefined가 뜨게 된다. 



함수선언의 호이스팅


1
2
3
4
5
doSomething();
 
function doSomething() {
    console.log("doing something");
}
cs


함수선언도 호이스팅이 되어서 함수가 선언되기도 전에 함수를 실행할 수 있다!



1
2
3
4
5
6
7
doSomething();
 
var doSomething = function() {
    console.log("doing something");
 
}
 
cs


하지만 함수를 변수에 할당하는 경우, 변수는 호이스팅이 되지만 함수의 몸체를 변수에 할당하는 동작은 위의 '초기화' 처럼 호이스팅이 되지 않는다.

마찬가지로 실행하면 undefined가 뜨게 된다.



ES6 에서의 개선점


ES6에서는 스코프 문제를 letconst로 해결한다!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html>
  <body>
    <script>
      "user strict";
 
      let customer = "Joe";
 
      (function() {
        console.log("inside function : " + customer);
 
        if(2>1) {
          let customer = "Mary";
          console.log("inside block : "  + customer);
        }
      })();
 
      for(let i=0; i<10; i++) {
 
      }
 
      console.log(i);
    </script>
  </body>
</html>
 
cs


선언을 let을 이용해서 해주면 이 변수는 스코프를 갖게 된다. 즉 마지막에 i를 찍는 것도 for문안의 i는 딱 거기서만 쓰이게 되므로 undefined가 나오게 된다.




const키워드는 변수가 상수로 선언되고 할당된 이후 값을 변경할 수가 없다. 이제 코드를 작성할 때 let과 const를 이용해 편하게 작성할 수 있게 되었다.


출처 : 속깊은 Javascript, Angular Development with Typescript





반응형