지난 포스트(var를 지양해야 하는 이유)의 내용을 호이스팅과 TDZ(Temporal Dead Zone)의 개념을 가지고 보충한다.
함수가 실행되기 전에 안에 있던 변수들을 범위의 최상단으로 끌어올려 주는 것을 호이스팅이라고 한다. 코드를 실행시킬 때, 코드 실행 전에 자바스크립트 엔진이 코드를 훑으면서 무슨 변수와 함수가 있는지 확인한다. 그리고 확인한 것들을 메모리에 기억을 해 뒀다가, 나중에 변수를 불렀을 때 찾아다 주는 것이 호이스팅이다.
var a = 1;
console.log(a);
위의 코드에서, 자바스크립트 엔진은 a가 선언된 것을 확인하고 console.log(a)
에서 a가 호출되었을 때 기억해 뒀던 a를 불러준다. 전혀 문제가 없는 코드이다.
console.log(a);
var a = 1;
console.log(a);
그런데 이런 경우는 어떨까? a를 선언하기도 전에 console.log(a)
로 a를 호출한다. 당연히 에러가 날 것 같은 코드인데 에러가 나지 않는다.
첫 번째 콘솔의 결과로 undefined
가, 두 번째 콘솔의 결과로 1이 나오는 것을 확인할 수 있다!
console.log(a);
위와 같이 아예 변수를 선언하지 않으면? 이제서야 에러가 나온다.
console.log(a);
var a = 1;
console.log(a);
이런 말도 안되는 로직에 에러가 나지 않는 이유는 호이스팅 때문이다. 첫 번째 코드가 콘솔 창에 나오기 전에, 자바스크립트 엔진이 먼저 a라는 변수가 선언된 것을 확인한다. "a라는 변수가 있네? 저장해둬야지" 하고 그 후에 1번 라인이 실행되는 것이다. 1번 라인에서 a를 호출할 때, a를 undefined
값으로 주는데, 아직 2번 라인에서 a를 1로 할당하기 전이기 때문이다.
즉, 자바스크립트는 호이스팅을 할 때 변수의 선언과 초기화(undefined
로)를 같이 해버린다. 값 할당은 나중에 그 줄에 가서 하는 것이다.
이런 것도 가능하다.
변수 할당을 먼저 하고 선언을 나중에 하는 이상한 코드도 에러가 안 나고 잘 동작하는 것을 확인할 수 있다.
var
는 함수 스코프를 가지기 때문에, for문이나 if문의 scope를 벗어난다.
var a = "전역";
function test() {
var b = "지역";
}
console.log(a);
console.log(b);
함수 밖에 선언된 a는 잘 호출이 되지만, b를 호출하면 에러가 날 것이다.
for(var i=0; i<5; i++){
console.log(i);
}
console.log(i);
그런데 위의 코드를 실행시켜 보면, i가 4가 아니라 5까지 출력되는 것을 확인할 수 있다.
변수 i는 for문 안에서 선언된 지역변수인데, 바깥에서도 자유롭게 사용이 가능한 것이다. var
는 함수만 지역변수로 호이스팅이 되고, 나머지는 다 전역변수로 호이스팅이 되는 문제가 있다.
자바스크립트에서는 이렇게 같은 이름을 가진 변수가 두 개 존재하는 것도 가능하다. 이런 이상한 일들이 가능하게 되니까 자바스크립트 측에서도 var
를 없애고자 새로운 변수 선언방식을 내놓았는데, 그게 let
인 것이다.
var
를 let
으로 바꾸고 같은 코드를 다시 돌려보면, 정상적으로(?) 에러가 나는 것을 확인할 수 있다. 위에서 var
를 가지고 run해 봤었던 이상한 코드들도, let
으로 바꿨을 때 모두 에러가 난다.
let
은 어떻게 이런 호이스팅 문제를 해결했을까? let
도 호이스팅이 되긴 된다. 그런데 Temporal Dead Zone이라는 개념이 적용된다.
console.log(a); // 여기는 TDZ, 에러 발생
let a = 1; // 선언
console.log(a); // 여기서부터 a를 쓸 수 있음
let을 사용하면 a가 호이스팅으로 기억이 됐긴 했지만, a 선언문이 나올 때까지 a에 접근할 수 없게 막아버린다. a가 선언되기 전까지는 일시적으로 죽은 zone으로 취급하는 것이다.
var
는 쓰지 말자. let
을 사용하자.
잘보고갑니다~~