상세 컨텐츠

본문 제목

let, var, const의 차이점과 호이스팅 (Hoisting)

카테고리 없음

by 리액트바오 2022. 4. 20. 13:21

본문

 

JavaScript에서 var, let, const의 차이는 무엇일까?

var

var로 선언한 변수는 같은 이름으로 여러번 중복해서 선언이 가능하다. 이때, 마지막에 할당된 값이 변수에 저장이 된다. 

var result = 'javascript';
console.log(result); // javascript

var result = 'nodeJS';
console.log(result); // nodeJS

위 코드를 보면 에러없이 같은 변수에 각각 다른 값이 출력이 되는것을 볼 수 있다. 필요에따라 변수의 값을 변경하여 유연하게 사용할 수 있다는 장점도 있지만 기존에 선언해둔 변수의 존재를 잊고 값을 재할당하는 실수를 한다면 의도치않게 값이 바뀔 우려가 있다는 단점도 있다.

이를 보완하기 위해 ES6에서 추가된 변수 선언방식이 let과 const이다.  var는 Hoisting과도 연관이 있다. var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화한다. 반면 let과 const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않는다.

 

let

let은 변수의 재할당이 가능하다. 단, 재선언은 불가하다.

let result = 'javascript'
console.log(result) // 'javascript'

result = 'nodeJS'
console.log(result) // 'nodeJS'

위와 같이 변수에 다른 값을 재할당 하면 재할당한 값을 출력하는 것을 확인할 수 있다. 또한, let은 변수를 선언할 때 할당을 반드시 하지 않아도 된다.

let result;
console.log(result) // undefined

result = 'javascript'
console.log(result) // 'javascript'

 

const

const는 변수의 재선언, 재할당 모두 불가능하다. 변수에 값을 한 번 할당하게 되면 바꿀 수 없기 때문에 변수를 선언할 시 할당이 반드시 이루어져야 한다.

const result = javascript
result = nodeJS // TypeError: Assignment to constant variable.

const result // SyntaxError: Missing initializer in const declaration

위의 예시와 같이 const로 선언한 변수는 값을 재할당할 수 없으며, 변수를 선언만 하는 것도 불가능하다.

 

그럼 여기서 잠깐!

const a = [];
a.push('aaaa');	// ['aaaa']

const b = [];
b = ['bbbb'];	// error

const b = ['bbbb'];	// error

const로 선언한 a에 'aaaa'를 push 했을때 어째서 들어가게 되는가? 분명 const는 재선언과 재할당이 되지 않는다고 했는데,, 

이유는 push와 pop 행위가 재할당/재선언이 아니기 때문이다.

 

Hoisting

호이스팅이란 미리 선언문을 실행해둔것처럼 함수 내부에 있는 선언들을 모두 끌어올려 해당 함수 유효 범위의 최상단에 선언하는 것을 뜻한다.

var, 함수선언문

호이스팅이 발생한다.

console.log(result); // undefined

var result = javascript;
console.log(result); // javascript


hello(); // hello

function hello() {
	console.log("hello");
}

변수 result가 선언되기 전에  참조되었음에도 에러가 발생하지 않은것은 코드 실행 전에 자바스크립트 내부에서 미리 변수를 선언하고 undefined로 초기화를 해두었기 때문이다. 함수 선언문 또한 동일하게 선언되기 전 호출되었지만 에러가 발생하지 않는다.

 

let, const, 함수표현식 

호이스팅이 발생하지만, 다른 방식으로 작동된다.

console.log(result); // ReferenceError: a is not defined

let result = javascript;
console.log(result); // javascript

hello(); // error

var hello = function() {
	console.log("hello");
}
변수 result가 선언되기 전에 참조했기 때문에 에러가 발생한다. 이는 호이스팅이 발생하지 않는것이 아니라 변수의 선언과 초기화 사이에 일시적으로 참조할 수 없는 구간인 TDZ(Temporal Dead Zone)에 빠졌기 때문에 보이는 현상이다. 
 
TDZ(Temporal Dead Zone): 한글로 직역하면 일시적인 사각지대란 뜻이다. TDZ는 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 말한다.
 
그럼 스코프는 뭘까? 이렇게 꼬리를 물고 늘어지다간 끝도 없을테니 스코프는 따로 포스팅해야겠다 ㅎㅎ 하하
 

어쨌든 let 또한 선언전, 실행 컨텍스트 변수 객체에 등록이 되어 호이스팅이 되지만, 이 TDZ 구간에 의해 메모리가 할당 되지 않아 참조 에러가(ReferenceError) 발생하는 것 이다.

함수 표현식을 사용하거나 let 또는 const로 변수를 선언하는 경우, 자바스크립트 내부에서는 코드 실행 전 변수만 선언만 해둘뿐 초기화는 코드 실행과정에서 변수 선언문을 만났을때 수행하기 때문에 호이스팅이 발생하긴 하지만 값을 참조할 수 없어서 동작하지 않는것처럼 보이는것이다. 
 
 
요약하면

var: 변수의 재선언,재할당 모두 가능하다. 

let: 변수의 재할당은 가능,재선언은 불가능하다. 변수를 선언하고 할당을 즉시 하지 않아도 된다. 꼭 할당을 하지 않아도 된다.

const: 변수의 재할당,재선언 모두 불가능하다. 변수를 선언하기 전에 참조할 수 없으며, 변수를 선언할 시 할당도 반드시 해야 한다.

hoisting: 호이스팅(hoisting)이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미합니다. var 로 선언한 변수의 경우 호이스팅 시 undefined 로 변수를 초기화합니다.