본문 바로가기

이것저것 스터디📚/JavaScript

var, let, const 차이

- var와 ES2015(ES6)에서 추가된 let, const는 JavaScript에서 변수를 선언하는 키워드이다.

- var, let, const는 변수를 선언하는 키워드라는 공통점이 있지만, 재선언과 재할당 가능성, 범위(Scope), 호이스팅(Hoisting)에서 차이점을 가지고 있다.

 

※ 재선언, 재할당

- 재선언 : 동일한 이름의 변수를 같은 스코프 내에서 두 번 이상 선언하는 것을 의미힌다.

- 재할당 : 이미 선언된 변수에 새로운 값을 할당하는 것을 의미한다.

 

- var재선언, 재할당이 모두 가능하다.

var name = 'poco'
console.log(name); // 'poco'

// 재선언
var name = "Kim"
console.log(name); // "Kim"

// 재할당
name = "Lee"
console.log(name); // "Lee"
// var는 재선언과 재할당이 모두 가능하다

 

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

let age = 25;
console.log(age); // 25

// 재선언
let age = 30;
console.log(age); // SyntaxError: Identifier 'age' has already been declared

// 재할당
age = 28;
console.log(age) // 28

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

 

- const는 재선언, 재할당이 모두 불가능하다.

const gender = "male";
console.log(gender); // "male"

// 재선언
const gender = "female"; // SyntaxError : Identifier 'gender' has already been declared

// 재할당
gender = "female"; // TypeError: Assignment to constant variable.

// const는 재선언과 재할당 모두 불가능하다.

 

※ var, let, const의 Scope

- Scope(범위)는 기본적으로 변수를 사용할 수 있는 위치를 의미한다.

- var함수 레벨 스코프(function-level scope), letconst블록 레벨 스코프(block-level scope)를 갖는다.

- 함수 레벨 스코프(function-level scope) : 함수 내에서 선언된 변수는 함수 내에서만 유효하며 함수 외부에서는 참조할 수 없다. 즉, 함수 내부에서 선언한 변수는 지역 변수이며 함수 외부에서 선언한 변수는 모두 전역 변수이다.

- 블록 레벨 스코프(block-level scope) : 모든 코드 블록(함수, if문, for문 while문 등) 내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다.

 

- var함수 레벨 스코프(function-level scope)를 갖는다.

var country = "Korea";

if(true) {
  var city = "Seoul";
}

console.log(`Country : ${country}, City : ${city}`) // Country : Korea, City : Seoul

// var로 선언한 변수 함수 레벨 스코프를 갖기 때문에 if문 내부에 있더라도 if문 밖에서 참조할 수 있다.

 

- letconst블록 레벨 스코프(block-level scope)를 갖는다.

- 즉, letconst의 스코프를 결정하는 것은 중괄호("{}")이다.

const country = "Korea";

if(true) {
  const city = "Seoul";
}

console.log(`Country : ${country}, City : ${city}`) // Uncaught ReferenceError: city is not defined
    at <anonymous>:7:45

// let이나 const로 선언한 변수는 블록 레벨 스코프를 갖기 때문에 if문 내부에서 선언된 변수를 if문 외부에서 참조할 수 없다.

 

※ Window 객체 요소 추가

- var를 이용해서 전역변수를 만들면 window 객체에 key와 value로 추가된다.

- letconst를 이용해서 전역변수를 만들면 window 객체에 추가되지 않는다.

var country = "Korea";
console.log(window.country); // "Korea"

let city = "Seoul";
console.log(window.city); // undefined

const district = "Gang-nam";
console.log(window.district); // undefined

 

※ 변수 호이스팅(hoisting)

- 호이스팅 : 호이스팅은 JavaScript에서 변수와 함수 선언이 해당 스코프의 최상단으로 끌어올려지는 것처럼 보이는 JavaScript의 기본동작을 말한다.

- 이는 JavaScript 엔진이 코드를 실행하기 전 실행 가능한 코드를 형상화하고 구분하는 과정을 거치기 때문이며, 해당 과정에서 모든 선언(var, let, const, function, class)을 스코프에 등록한다.

- 즉, 호이스팅은 선언이 코드 실행 보다 먼저 메모리에 저장되는 과정으로 인한 현상을 말한다.

- JavaScript의 모든 선언에는 호이스팅이 일어나지만, let, const, class를 이용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다.(여기서는 변수 선언만 다루겠다.)

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

console.log(c); // undefined -> 호이스팅은 선언만 해당 스코프 상단으로 끌어올려진다. 할당은 x
var c = 10;

console.log(b); // 참조 에러 발생
let b;

console.log(d); // 참조 에러 발생
const d = 15; // const는 선언과 할당을 동시에 해야한다. 그럼에도 불구하고 참조 에러가 발생하는 것은
// 호이스팅은 선언만 해당 스코프 상단으로 끌어올려지기 때문이다.

 

- 위 예제를 보면 var 키워드로 선언한 a 변수는 변수 선언보다 먼저 참조를 했을 때, 에러가 발생하는 것이 아닌 undefined를 반환하지만, let 키워드로 선언한 b 변수는 변수 선언보다 먼저 참조를 했을 때, 참조 에러가 발생한다.

- 그 이유는, var 키워드로 선언한 변수는 선언과 함께 초기화(undefined로)가 되어 메모리에 undefined가 저장되지만, let, const 키워드로 선언한 변수는 선언만 메모리에 저장되기 때문이다.

- 변수 생성은 총 3단계로 이루어져 있다.

   1. 선언 단계(Declaration phase) : 변수를 실행 컨텍스트의 변수 객체에 등록한다.

   2. 초기화 단계(Initialization phase) : 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보하고 undefined로 초기화한다.

   3. 할당 단계(Assignment phase) : undefined로 초기화된 변수에 실제 값을 할당한다.

 

- var, let, const 키워드별 변수 생성 단계는 다음과 같다.

- var로 선언된 변수는 선언과 동시에 초기화가 진행된다. 실제 값의 할당은 실제 코드 실행 시점에 진행된다.

var country; 
console.log(country); // undefined
var country = 'Korea'
console.log(country); // 'Korea'

// 1. 선언 + 초기화 2. 할당
// var는 선언과 동시에 초기화(undefined 할당) 단계가 진행이 되지만, 실제 값의 할당은
// 실제 코드 실행시점에 진행된다.

- let으로 선언된 변수는 선언은 되지만, 초기화는 실제 코드에 도달했을 때 진행된다.

console.log(country); // ReferenceError: Cannot access 'country' before initialization
let country; // undefined로 초기화
console.log(country); // undefined 
country = "Korea";
console.log(country); // "Korea"

// 1. 선언 2. 초기화 3. 할당
// var와 달리 let은 호이스팅이 되면서 선언은 되었지만, 초기화는 실제 코드(할당)에 도달했을 때,
// 실행되기 때문에 country에 대한 초기화(undefined 할당)가 되지 않은 상태로 참조 에러 발생

- const로 선언된 변수는 선언과 초기화, 할당이 동시에 되어야 한다.

const gender; // Uncaught SyntaxError: Missing initializer in const declaration
gender = 'male'

// 1. 선언 + (초기화) + 할당
// const는 선언과 할당이 동시에 되야한다.

 

- let과 const로 선언된 변수도 호이스팅이 발생하지만, 실제 코드에 도달하기 전까지 TDZ(Temporal Dead Zone)에 빠진다.

- TDZ(Temporal Dead Zone, 일시적 사각 지대) : 스코프의 시작 지점부터 초기화 시작 지점까지의 구간으로 초기화 이전에는 접근할 수 없는 구간이다.

- 즉, JavaScript의 모든 선언은 호이스팅이 발생하지만, var, let, const 키워드의 변수 선언 단계 차이로 인해 let, const 키워드로 선언된 변수는 초기화 시작 지점 전까지 TDZ에 빠져 초기화 시작 지점 전에 변수를 참조하면 참조 에러가 발생한다.


학습 단계로 잘못된 정보가 있을 수 있습니다. 잘못된 부분에 대해 알려주시면 정정하도록 하겠습니다.

참고 : https://velog.io/@grinding_hannah/JavaScript-var-let-const-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90

https://hanamon.kr/javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85%EC%9D%B4%EB%9E%80-hoisting/

'이것저것 스터디📚 > JavaScript' 카테고리의 다른 글

call, apply, bind  (0) 2024.01.14
가비지 컬렉션  (0) 2023.12.19
커링과 클로저  (2) 2023.12.05
React에서 서버와 통신하는 과정을 구현하는 방법  (1) 2023.11.21
Virtual DOM이란?  (1) 2023.11.21