변수는 스코프(scope, 범위)라는 것을 가진다. var는 함수 스코프를 가지고, let은 블록 스코프를 가진다.
아래의 코드로 예를 들겠다.
function b() {
var a=1;
}
console.log(a); //a is not defined
a를 콘솔로 출력하면 에러가 발생한다. a는 함수 안에 선언된 변수이므로 함수 바깥에서는 접근할 수 없다. 이렇듯 함수를 경계로 접근 여부가 달라지는 것을 함수 스코프라고 한다.
if (true) {
var a=1;
}
console.log(a); //1
var는 함수 스코프(함수만 신경 씀)라서 if문 안에 들어 있으면 바깥에서 접근할 수 있지만
let은 아니다.
if (true) {
let a=1;
}
console.log(a); //a is not defined
let의 경우에는 에러가 발생한다. 바로 let이 블록 스코프(블록을 신경 씀)라서 그렇다. 블록은 if문, for문, while문, 함수에서 볼 수 있는 {}를 의미한다. 블록 바깥에서는 블록 안에 있는 let에 접근할 수 없다. const도 let과 마찬가지로 블록 스코프를 가진다.
for문을 보면
for (var i=0; i<5; i++){} //i가 4일 때 반복은 안돌지만 최종적으로 i++이기 때문에 하나가 더 추가되고 끝남
console.log(i); //5
var는 블록과 관계가 없어서 문제없이 돌아간다. for문이 끝났을 때 i가 5가 되어 있다는 점에 주목하자.
이와 다르게 let은 에러가 발생한다. for문 블록 바깥에서 접근했기 때문이다. 위치 상으로는 let이 블록 바깥에 있지만, for문의 경우는 블록 안에 있는 것으로 간주한다.
함수와 함수 바깥에 있는 변수의 관계
함수 스코프를 가진 var과 비동기 함수가 만나면 매우 복잡한 클로저 문제와 직면할 수 있다.
따라서 var보다 let 사용을 추천!