본문 바로가기
인간은 어떻게 배울까

[JS] var와 let의 차이

by 개발하는 아인 2023. 6. 9.

1. var는 재선언이 가능하다.

    let은 재선언이 불가능하다. (재할당은 가능)

 

2. var는 호이스팅이 가능하다.

    let은 호이스팅 되지 않는다.

 

3. var는 함수 스코프를 가진다.

    let은 블록 스코프를 가진다.

  재선언 호이스팅 스코프
var O O 함수
let X X 블록

 

 

 

무슨 뜻인지 차근차근 알아보자.

 

 


1. var : 재선언 가능 (재할당 가능)

    let : 재선언 불가능 (재할당 가능)

 

var부터 살펴보자.

var는 자바스크립트 초창기부터 사용해온 변수 선언 키워드이다. 뒤에서 다시 이야기하겠지만 let은 var를 좀더 보완해서 나온 것으로 한참 후에 등장했다.

먼저 var a = 23으로 선언하고, 그 뒤에 다시 var a = 999 라고 선언해도 아무 문제가 없다.

 

 

 

이번에는 let을 살펴보자.

let은 2015년 ES6(ECMAScript 6 이후 통칭)에서 도입되었다. var가 야기할 수 있는 여러 문제들을 보완하기 위해 const와 함께 등장한 새로운 키워드로 var보다 권장되고 있다.

let은 재선언이 불가능하고, 재할당은 가능하다. 

let은 재선언이 불가능하기 때문에 아래에서 let a = 999 라고 재선언을 시도하는 순간 SyntaxError가 발생한다. 우측의 에러메시지가 보일 것이다.

 

 

 

하지만 아래처럼 재할당하는 것은 아무 문제가 없다.

 

 

 


 

2. var는 호이스팅이 가능하다.

    let은 호이스팅 되지 않는다.

 

 

var로 변수를 선언하면, 호이스팅(끌어올리기)이 가능해진다.     

*호이스팅: 변수 선언이 맨 위로 끌어올려지는 것

 

var a = 23이 첫줄의 console.log보다 아래에 있지만, 호이스팅 덕분에 첫줄의 console.log(a) 를 실행해도 에러가 나지는 않는다.

 

다만, 선언은 유효하지만 할당은 아니다. 

이게 무슨 말이냐면, 아래에서 a라는 변수를 선언했지만 호이스팅으로 끌어올려서 a라는 변수가 존재하는 건 인정해줌.

But, 변수에 23이라는 값을 할당한 건 반영을 안해준다. 그래서 첫줄의 console.log(a)로는 undefined(변수는 있으나 값이 아직 없다는 의미)가 나온다.

 

그러니까 위 코드는 사실상 아래의 흐름과 같다.

var a; // 변수 선언이 호이스팅되어 최상단으로 이동

console.log(a); // 변수 a에는 초기화되지 않은 상태이므로 undefined가 출력됨

a = 23; // 변수 a에 값 23을 할당
console.log(a); // 변수 a에 할당된 값 23이 출력됨

 

 

 

그럼 let은 어떨까.

let으로 선언하기 전에 변수를 불러내면 우측처럼 ReferenceError가 뜨는 것이 보일 것이다.

let으로 선언하면 호이스팅이 되지 않기 때문에 저 시점에서는 a라는 변수 자체가 없어서, 참조를 할 수 없다는 메세지가 뜬다.

 

 

 

 

 

 


3. var는 함수 스코프를 가진다.

    let은 블록 스코프를 가진다.

var로 선언한 변수는 '함수' 단위의 영역(스코프)를 가진다.

즉, 이름이 똑같은 변수가 함수 안과 밖에 존재할 때, 함수를 기준으로 영역을 가른다.

그래서 이 코드에서는 함수 내부에서 쓰이는 a함수 밖에서 쓰이는 a 두 가지의 a만 존재한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

반면 let으로 선언하면 블록 { } 단위의 영역(스코프)를 가진다.

 

왼쪽 코드를 보면, b라는 변수는 실제론 3가지가 존재한다.

 

블록 { } 단위로 영역이 나뉘므로,

함수 밖의 b(5), 함수 안의 b(123) 그리고 if문 안의 b(999) 이렇게 3가지가 존재하게 된다.

 

test2()의 결과로 123 이 출력되는 것은, 블록스코프인 let의 특성상 if문 블럭 { } 안에서 선언된 let b = 999가 if문 블럭 { }밖의 b에게는 영향을 미치지 못하기 때문이다.

블록 스코프를 가지는 let으로 변수를 선언하면, 중괄호{ } 가 붙는 모든 블럭(함수, for문, if문 등) 안에서 선언된 변수가 해당 블록 밖으로 영향을 미치지 못한다.

 

var로 선언된 변수는 함수 스코프를 가지므로 함수{ } 밖을 벗어나지 못할 뿐, 그 안에서는 for문 안에 들어있던 if문 안에 들어있던 다 통용된다.

 

 

 

 

 

 

주의할 것이 있다.

 

이 코드는 위와 다르게 함수가 999를 반환한다. 즉 if문 { } 안에서 b 값이 재할당되었다. 

위에서는 if문 { } 안에서 let으로 선언을 해주었기 때문에 또 다른 b가 생겨난 것이고, 여기서는 선언없이 999라는 값만 할당해주었다.

때문에, 이 코드 전체에서는 함수 밖의 b와 함수 안의 b 두가지만 존재한다. 

 

 

 

 

 

 

 

 

 

 


 

이쯤되서 처음의 요약을 다시 한번 보자.

  재선언 호이스팅 스코프
var O O 함수
let X X 블록

 

 

 

var과 let의 차이 끝-