var, let, const를 배우면서 가장 헷갈렸던 부분은 var이었다. var과 let과 const와는 어떻게 다른 걸까? 왜 var을 쓰는 것은 권장되지 않는 것일까?
var foo = 123;
console.log(foo); // 123
{
var foo = 456;
}
console.log(foo); // 456
Var는 함수 레벨 스코프를 따른다. 따라서 블록 안에서 정의 되었다고 하더라도 블록 밖에서도 출력이 가능하다.
let foo = 123;
{
let foo = 456;
let bar = 456;
}
console.log(foo); // 123
console.log(bar); // ReferenceError: bar is not defined
반면 let 또는 const는 블록 레벨 스코프를 따른다. 블록 바깥에서 선언된 foo는 출력이 되었지만 블록 안쪽에서 선언된 bar는 ReferenceError를 내뱉는다.
그럼 호이스팅이라는 것은 무엇일까? JavaScript는 함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당하는데 이것을 호이스팅이라고 한다.
다음의 예시를 보자.
function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
catName("호랑이");
/*
결과: "제 고양이의 이름은 호랑이입니다"
*/
catName("클로이");
function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
/*
결과: "제 고양이의 이름은 클로이입니다"
*/
위 두개의 코드는 모두 에러 없이 동작하는 코드이다. 함수를 선언한 후에 함수를 호출을 하든, 선언 전에 호출을 하든 모두 잘 동작한다. 호이스팅이 어떻게 작동하는지 확인할 수 있다.
console.log(num); // 호이스팅한 var 선언으로 인해 undefined 출력
var num; // 선언
num = 6; // 초기화
var로 선언한 변수의 경우 호이스팅 시 undefined 로 변수를 초기화한다. 위 코드는 다음과 같은 순서로 작동한다. 맨 첫번째 줄에서는 함수가 선언만 되어있고 값이 할당은 되어있지 않기 때문에 undefined가 뜬다.
이와는 다르게 let/const는 호이스팅 시 변수를 초기화하지 않는다. 이 경우에는 아예 ReferenceError를 발생시킨다.
console.log(typeof i); // ReferenceError
let i = 10;
위와 같은 문제 때문에 let, const가 새롭게 등장하였고 var은 더이상 쓰이지 않는다.