Programming/JavaScript

var, let, const

JavaScript 에서 변수 선언시 var, let, const 를 사용하게 되는데, 이 차이점에 대해 알아보자.

 

1. var ( 변수 재선언 가능, 변수 재할당 가능)

var v1 = 'v1';
console.log(v1);	//v1

var v1 = 'v123';
console.log(v1);	//v123

var로 선언한 변수는 중복해서 선언 및 초기화가 가능하다. (에러 X)

마지막에 할당된 값이 변수에 저장된다.

 

유연한 변수 선언으로 간단한 테스트에는 편리 할 수 있겠으나, 코드량이 많아 진다면 어디에 어떻게 사용 되는지 파악하기 힘들 뿐만 아니라, 값이 바뀔 우려가 있다.

 

💡 var은 function-scoped 단위로 hoisting이 일어난다.

hoisting 이란 : '변수 선언문' 을 미리 실행해두기 때문에 뒤에서 선언된 변수도 앞의 코드에서 참조 할 수 있게 되는데, 이를 변수 호이스팅 이라고 한다.

 

먼저, var변수에서는 함수 내부에 선언된 변수만 지역변수로 한정한다.

function f1(){
	var a = 10;
    console.log(a);
}

f1();	//10

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

 

그외의 나머지( if문, for문, while문, try/catch문 등의 코드 블럭{ ... } 내부에서 )는 var로 선언된 변수를 전역 변수로 간주한다.

for(var i=0; i<10; i++){
	console.log('i', i);
}

//var i가 hoisting 됨
console.log('after loop i is ', i);	// after loop i is 10

 

# 직관적으로 살펴보자

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

var a = 10;

console.log(a);	//10

코드 실행 전에 자바스크립트 엔진이 미리 변수를 선언하고, undefined로 초기화 해두었기 때문에 앞에서 var로 선언한 변수 a를 참조한 코드에도 에러를 발생시키지 않는다.

 

2. let ( 변수 재선언 불가능, 변수 재할당 가능)

let l1 = 'let 변수';
console.log(l1);	//let 변수

l1 = '재할당';
console.log(l1);	//재할당

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

let 변수는 재할당이 가능하지만, var와는 다르게 재선언이 불가능하다.

 

 

3. const (변수 재선언 불가능, 변수 재할당 불가능)

const c1 = 'const 변수';
console.log(c1);	//const 변수

const c1 = 'const 변수'; 
console.log(c1); // Uncaught SyntaxError: Identifier 'c1' has already been declared

c1 = '재할당 TEST';    // Uncaught TypeError:Assignment to constant variable.

const 변수는 constant(상수) 로 한 번만 선언하고, 재 할당 및 재 선언이 불가능 하다.

 

처음 선언할 때 반드시 초기화(값 할당)을 해주어야 한다.

const c2;	//SyntaxError: Missing initializer in const declaration

 

💡 let 과 const 는 block-level scoped  단위로 hoisting이 일어난다.

let/const로 변수를 선언하는 경우, 코드 실행 전에는 변수 선언만 해두며, 초기화는 코드 실행 과정에서 변수 선언문을 만났을때 수행한다.

 

let, const는 함수 내부는 물론, if문이나 for문 등의 코드블럭 { ... } 에서 선언된 변수도 지역변수로 취급한다.

if(true){
	let a = 10;
    console.log(a); //10
}

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

function f2(){
	let b = 10;
    console.log(b);	//10
}

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

if문의 블럭 내부에서 선언된 let 변수와, 함수 내부에서 선언된 let 변수 역시 외부에서 참조 할 수 없다.

 

l4 = 'test';	// ReferenceError: c is not defined
let l4;

let 과 const가 hoisting이 일어나지 않는것은 아니다.

 

위의 코드에서 ReferenceError가 발생한 이유는 변수의 선언과 초기화 사이에 일시적으로 변수 값을 참조 할 수 없는 구간인 tdz(temporal dead zone) 때문인데, let 변수는 값을 할당하기 전에 변수가 선언 되있어야 하는데 그렇지 않기 때문에 에러가 난다.

 

const 변수는 좀 더 엄격하게, 선언과 동시에 값을 할당해야만 에러가 나지 않는다.

let l5;
l5 = 'NEXT';

const cst;	// Missing initializer in const declaration

 

# 직관적으로 살펴보자.

//1)
let a = 10;	//전역변수 a 선언

if(true){
	console.log(a);	//10
}

//2)
let b = 10;	//전역변수 b 선언
if(true){
	console.log(b);	//ReferenceError: a is not defined
	let b = 20;	//지역변수 b 선언
}

 

 

1) 코드를 보면, 전역변수로 선언된 a의 값 10을 if문 블럭에서 참조하여 출력하고 있다.

2) 코드를 보면, 전역변수 b가 있음에도 불구하고 ReferenceError 가 발생한다.

지역변수 b가 hositing 되면서 앞서 말한 tdz 구간이 만들어졌기 때문.

이를 통해, let으로 선언된 변수 역시도 호이스팅이 발생함 을 알 수 있다.

 

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

 


구글의 자바스크립트 스타일 가이드

Use const and let

 

Declare all local variables with either const or let.

Use const by default, unless a variable needs to be reassigned.

The var keyword must not be used.

 

1. const와 let을 이용해서 변수를 선언할것.

2. 값을 재할당하는 경우가 아니라면, const를 디폴트로 사용할것.

3. var는 절대로 사용하지 말것.

 

https://google.github.io/styleguide/jsguide.html#features-use-const-and-let