본문 바로가기
공부일지/Javascript

CS. var, let, const의 차이점 (feat. 호이스팅)

by 곰인간 2023. 1. 18.

/* 오늘도 어김없이..클론코딩만 하는 나에게 이런 시련이..

호이스팅 개념을 이해하는데 많은 시간을 썼다.. */

ps. 틀린곳도 많을거기 때문에 피드백은 항상 겸허히 받아들입니다.

 


변수의 선언은 var, let, const 키워드로 할 수 있으며, ES6에서 let과 const가 추가되었다.

자바스크립트에서 변수 선언은 선언 → 초기화 단계를 거쳐 수행된다.

더보기

선언 단계: 변수명을 등록하여 자바스크립트 엔진에 변수의 존재를 알린다.

초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.

왜 기존 var가 있는데, let과 const 추가 되었을까?


var, let, const에는 4가지 차이점이 있다.

1. 중복선언 가능 유무

2. 재할당 가능 유무

3. 변수 스코프 범위

4. 변수 호이스팅 방식


1 . 중복선언 가능 유무

* var : var는 중복 선언이 가능하다.

// 첫번째 변수 선언과 초기화
var a = 10;
console.log(a); // 10

// 두번째 변수 선언과 초기화
var a = 11;
console.log(a); // 11

// 세번째 변수 선언과 초기화
var a = 12;
console.log(a); / 12

var로 선언한 변수는 중복 선언이 가능하다. 그리고 마지막에 할당된 값이 변수에 저장된다.

var 키워드의 문제점은 크게 세 가지가 존재한다.

- 변수 중복 선언 가능하여, 예기치 못한 값을 반환할 수 있다.

- 함수 레벨 스코프로 인해 함수 외부에서 선언한 변수는 모두 전역 변수로 된다.

var a = 10;
if(true) {
	var a = 11;
}

console.log(a); // 11 
/* 함수가 아닌 곳에서 var 키워드를 이용해 a를 선언했기 때문에 전역 변수로 취급한다. 
(함수 레벨 스코프로 인해 함수 외부에서 선언한 변수는 모두 전역 변수로 된다.)*/

/* 기존에 있던 a 변수가 중복 선언되면서, 
최하단의 console에서도 출력 값이 11로 바뀐 것을 확인할 수 있다. 
(변수 중복 선언 가능하여, 예기치 못한 값을 반환할 수 있다.)*/

- 변수 선언문 이전에 변수를 참조하면 언제나 undefined를 반환한다.

var a
console.log(a); // undefined

 

* let, const : 중복 선언 불가

// let을 중복선언하면 이미 변수 a는 선언 되었다고 에러가 나온다.
let a = 10; 
console.log(a); // 10

let a = 11; 
console.log(a) // Uncaught SyntaxError: Identifier 'a' has already been declared

// const를 중복선언 해도 이미 변수 b는 선언 되었다고 에러가 나온다.
const b = 10;

const b = 11;
// Uncaught SyntaxError: Identifier 'b' has already been declared

 


2. 재할당 가능 유무

* varlet은 재할당이 가능하다.

var a = "바보";
a = "천재";
console.log(a); // 천재

let b = "평범";
b = "바보";
console.log(b); // 바보

* const는 재할당이 불가능..

const c = "천재";
c = "평범";
console.log(c); // Uncaught TypeError: Assignment to constant variable.

- const는 상수를 선언하는 키워드이다. 

* 상수 : 변하지 않는 값.

- const 선언과 초기화를 하면 다른 값을 재할당 할 수 없다.

- const는 선언할 때 초기화 값을 할당 해주어야 한다.

const c = "천재"
console.log(c); // 천재

const d
console.log(d); // Uncaught SyntaxError: Missing initializer in const declaration

3. 변수 스코프 범위

* var : 함수 레벨 스코프 

var는 함수 내부에서 선언된 변수만 지역변수로 인정한다. 함수 외에는 전역변수로 간주.

함수가 아닌 곳에서 var 키워드를 이용해 a를 선언했기 때문에 전역 변수로 취급한다.

기존에 있던 a 변수가 중복 선언되면서, 최하단의 console에서도 출력 값이 천재로 바뀌었다.

var a = "바보" // 전역변수

if(true) {
    var a = "천재" // 지역변수 
    console.log(a); // 천재
}

console.log(a); // 천재

* letconst는 블록 레벨 스코프이다.

 let 키워드로 선언한 경우 if 문 안에 있는 것은 지역 스코프를 가져 전역에서 console을 찍었을 경우,

전역에 있는 a가 결과 값으로 출력된다. (const 키워드도 let 키워드와 동일하게 동작한다)

let a = "바보" // 전역변수

if(true) {
    let a = "천재" // 지역변수
    console.log(a); // 천재
}

console.log(a); // 바보

 

* 전역 변수로 인해 재할당이 발생하거나,

전역 스코프를 공유하기 때문에 어딘가에 동일한 이름이 있다면 예상치 못한 결과를 가져올 수 있는 위험이 있다.

따라서 오로지 함수 코드 블록만을 지역 스코프로 인정하는 var 대신,

블록 레벨 스코프를 지원하는 const let을 사용하는 것을 권장한다.

 

#  지역변수가 전역변수보다 우선 순위를 갖는다.


4. 변수 호이스팅 방식

변수 호이스팅 방식을 알기 전에 호이스팅에 대해서 읽어보자..(ㅇ,어렵다.)

* 참고 자료 : MDN Web Docs - Hoisting

위 참고 자료 내용을 보면,

"var로 선언한 변수의 경우 호이스팅 시 undefined로 변수를 초기화합니다.

반면 let const로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않습니다."

 

* var 키워드를 이용한 변수 선언은 선언 단계와 초기화 단계가 동시에 진행되어,

변수 a에 암묵적으로 undefined를 할당해 초기화한다.

console.log(a); // undefined
var a /*선언*/ = "바보"; /*할당*/

 

# var는 선언하기 전에 사용 할 수 있다.

var a; // 선언은 호이스팅
console.log(a); // undefined
a = "바보"; //  할당 "바보" 는 호이스팅 x

# var는 선언은 호이스팅 되지만 할당은 호이스팅 되지 않음

이는 변수 선언이 런타임에서 되는 것이 아니라, 그 이전 단계에서 먼저 실행되기 때문이다. 자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기에 앞서, 변수 선언을 포함한 모든 선언문(ex. 변수 선언문, 함수 선언문 등)을 찾아내 먼저 실행한다. 즉, 변수 선언이 어디에 있든 상관없이 다른 코드보다 먼저 실행되는 특징을 호이스팅(hoisting)이라 한다.

변수 선언 뿐만 아니라, var, let, const, function, function*, class 키워드를 사용해 선언한 모든 식별자(변수, 함수, 클래스 등)는 호이스팅이 된다.

 

# let과 const 키워드로 넘어가기 전에,

호이스팅 : 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것 처럼 작동

* letconst는 TDZ(Temporal Dead Zone)라는 시간상 사각지대가 존재한다.

TDZ(Temporal Dead Zone)란, 변수가 스코프의 시작 지점부터 초기화가 시작되는 지점까지의 구간을 말한다.
let과 const키워드는 var키워드처럼 호이스팅(hoisting)이 일어난다.

console.log(a); // TDZ
let a = "바보"; // 함수 선언, 할당
console.log(a); // 바보

# const도 위와 같다.

# let과 const는 TDZ의 영향을 받음, 할당을 하기 전 까지 사용 하지 못 함.

(코드를 예측하게 하고, 잠재적인 버그를 줄 일 수 있음.)


var 

1. 선언 + 초기화

2. 할당


let

1. 선언

2. 초기화

3. 할당


const

1. 선언 + 초기화 + 할당


var a 
a = "평범";

let b;
b = "바보";

const c; // const는 선언만 하고, 할당하지 않았기 때문에 에러가 발생.
c = "천재"; 
// Uncaught SyntaxError: Missing initializer in const declaration

 

댓글