[JavaScript] var, let, const 정리 및 호이스팅

최별 Choi Byeol·2021년 12월 1일
0

JavaScript

목록 보기
1/1
post-thumbnail

자바스크립트에서 변수 선언은 var, let, const로 할 수 있으며, ES6에서 constlet이 추가되었다.

호이스팅(hoisting)이란?

자바스크립트는 실행 시점에 변수와 함수에 대해 호이스팅을 수행한다.
호이스팅이란 사전적 의미로 '끌어올린다'라는 뜻으로 코드에 선언된 변수와 함수를 맨 위로 끌어올려 동작하는 것을 말한다. 즉, 변수 선언이 어디에 있든 상관없이 다른 코드보다 먼저 실행되는 특징을 호이스팅(hoisting)이라 한다.
이는 자바스크립트 파서가 내부적으로 끌어올려 처리하는 것으로, 실제 메모리에는 변화가 없다.

흔히 알고 있는 var 키워드부터 정리해 보자.

console.log(name) // undefined
var name = 'star'

위의 코드는 첫 줄에 name을 출력하는데 에러가 나지 않고 undefined가 출력된다. 실행 시점에 호이스팅에 의해 var 변수가 최상단에 선언된 것으로 취급하기 때문이다. 따라서 해당 변수가 최상단으로 끌어올려져 undefined로 초기값이 할당되는 것이다.
따라서 변수가 선언되기 전에 변수를 사용할 수도 있다.

그렇다면 letconst는 어떻게 될까?

console.log(name) // ReferenceError: name is not defined
let name = 'star'

let으로 변수를 선언하면 에러가 발생한다. 그렇다면 호이스팅이 발생하지 않는 것일까?
그렇지 않다.
var뿐 아니라 letconst로 선언된 변수들도 호이스팅된다.

var name = 'star' // 전역변수

{
	console.log(name) // name is not defined
    let name = 'star' // 지역변수
}

최상단에 name 변수를 선언했으나 에러가 발생하는 것을 볼 수 있다. 이유는 블록 안에 let으로 선언된 name 변수가 호이스팅 되었기 때문이다. let name 변수가 호이스팅 되지 않았다면 console.log 결과는 star가 출력되어야 한다.

그렇다면 왜 출력 결과가 undefined가 아닌 name is not defined 에러가 발생한 것일까?
이를 이해하기 위해서는 자바스크립트에서 변수가 어떻게 생성되는지 알아야 한다.

 

변수 생성 과정

자바스크립트에서는 총 3단계에 걸쳐 변수를 생성한다.

  1. 선언(Declaration): 변수를 실행 컨텍스트의 변수 객체에 등록한다.
  2. 초기화(Initialization): 실행 컨텍스트에 등록된 변수 객체에 대해 메모리를 할당한다. 이 단계에서 변수는 undefined로 초기화된다.
  3. 할당(Assignment): undefined로 초기화되어있는 변수에 값을 할당한다.

var 키워드로 변수를 만들 경우, 선언 단계와 초기화 단계가 동시에 이루어진다. 아래의 예시를 다시 보자.

console.log(name) // undefined
var name = 'star'

위 코드에서 var로 선언된 변수는 호이스팅되어 선언과 초기화가 동시에 이루어지기 때문에 undefined로 출력된다.

하지만 let의 경우 선언과 초기화 단계가 분리되어 진행된다.

console.log(name) // ReferenceError: name is not defined
let name = 'star'

let 변수는 호이스팅되어 선언이 이루어지지만 초기화는 실제 let 코드에 도착했을 때 이루어진다. 따라서 초기화 이전에 변수에 접근하려고 하면 reference 에러가 발생한다.
즉, let 키워드로 선언한 변수는 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 일시적 사각지대(Temporal Dead Zone: TDZ) 구간에 존재한다.

 
const 변수
const는 let과 매우 유사하지만 const로 선언되면 상수화되어 값을 변경할 수 없다. 또한 const로 선언하는 경우는 선언과 동시에 초기화를 해야한다.

console.log(name) // ReferenceError: Cannot access 'name' before initialization
const name = 'star'

let 키워드로 선언한 경우, 런타임 이전에 선언되어 자바스크립트 엔진에 존재하지만, 초기화되지 않았기 때문에 name is not defined 문구가 출력되었다. const로 선언한 경우, 선언과 동시에 초기화가 이루어져야 하기에 런타임 이전에 실행될 수 없다. 따라서 초기화가 진행되지 않은 상태이기 때문에 Cannot access 'name' before initialization 문구가 출력된다.

const는 let과 마찬가지로, 재선언이 불가하며, 더 나아가 재할당도 불가능하다. 재할당의 경우, 원시값은 불가능하지만, 객체는 가능하다. const는 재할당을 금지하는 것이며, '불변'을 의미하지는 않는다.

const name = 'star' 
name = 'byeol' // TypeError: Assignment to constant variable.
// 원시값의 재할당은 불가능

const person = {
	name: 'star',
}
person.name = 'byeol'
// 객체의 재할당은 가능

console.log(name); // { name: "byeol" }

변수 Scope

let/constvar와 또 다른 차이가 있다. 바로 블록 레벨 스코프를 가진다는 것이다. 즉, {} 내부에 변수를 선언하면 해당 블록 내부에서만 생명주기를 유지한다. 반대로 var 변수는 함수 레벨 스코프를 가지므로, 블록 내부에 선언되어도 외부에서 접근이 가능하다.

{
	let name = 'star'	
}
console.log(name) // ReferenceError: name is not defined

{
	var age = 24;
}
console.log(age) // 24

 

결론

  • 호이스팅은 변수, 함수 선언을 최상단에 끌어올리는 것이다.
  • var, let, const는 모두 호이스팅된다.
  • let 선언은 동시에 TDZ에 들어가서 초기화가 필요한 별도의 상태로 관리된다.
  • const는 선언과 동시에 초기화, 할당까지 이루어진다.
  • var는 함수 레벨 스코프, let/const는 블록 레벨 스코프를 가진다.
  • var 사용은 지양하고, let/const를 적절히 사용하여 코드를 작성하자.

호이스팅 메커니즘을 이해하는 것도 중요하지만, 호이스팅에 의해 발생하는 혼란과 버그를 방지하기 위해 변수 선언과 초기화는 스코프 최상단에서 하도록 하자.

profile
FE 👩🏻‍💻

0개의 댓글