[TIL][JavaScript] var, let, const 그리고 호이스팅

Heejun Kwon·2021년 6월 17일
0

TIL

목록 보기
3/5
post-thumbnail

본 TIL( Today I Learned )은 그날그날의 공부한 내용들을
나중에 보더라도 쉽게 찾을 수 있도록 정리하고 있습니다.

잘못된 부분과 새로 배우는 내용이 있을 경우나
더욱 가독성이 좋아지도록 지속적으로 수정될 예정입니다.

1차 작성일자 : 2021.06.17
2차 수정일자 :

1. var


var은 ES6(ECMAScript2015) 이전부터
변수 선언에 사용되어온 키워드이다.

1. 재선언 : 가능 / 재할당 : 가능

var one = "a";
console.log(one); 	//결과 a
//
var one;		//결과 에러발생 X
console.log(one); 	//결과 a
//
one = "b";		//결과 에러발생 X
console.log(one); 	//결과 b

var은 같은 범위(Scope) 내에서 재선언, 재할당이 모두 가능한
좋게 말하면 상당히 유연하고,
나쁘게 말하면 문제를 일으킬 여지가 많은 변수 선언 키워드이다.

위의 예시를 보면 var 키워드로 one 변수를 선언한 뒤
다시 한 번 같은 이름으로 변수를 선언했는데 에러가 발생하지 않으며
기존 one에 남아있던 값도 그대로 남아있다.

만약 협업을 하는 과정이나 다른사람이 유지보수를 하는 과정에서
기존 변수의 존재를 모르고, 같은 이름으로 변수를 선언해 사용하면
기능들이 오작동하거나 유지보수를 매우 어렵게 만드는 등
여러가지 문제를 유발할 수 있다.

2. 범위(Scope) : FS(Function Scope, 함수 범위)

(function() {
	if(true){
		var num = 3;
		console.log(num);	//결과 3
	}
	console.log(num);		//결과 3
})();
console.log(num);			//결과 에러발생

var 키워드로 선언한 변수의 범위는
함수 범위(Function Scope)이다.

본인이 속한 블록( { } ) 내에서만 참조가 가능한 블록 범위와 달리
함수 범위는 본인이 속한 함수 블록 안에서 참조가 가능하다.

만약 블록 범위였다면 if문 내에서만 참조가 가능했겠지만
if문 밖에서도 참조가 가능한 이유는 함수 범위이기 때문이다.

만약 함수 밖에서 선언을 했다면 GS(Global Scope)
즉, 전역 변수로 어디서든 참조할 수 있게 된다.

3. 초기값 할당 필수 여부 : X

var one;	//결과 에러발생X

변수를 선언하며 초기화를 하지 않아도 에러가 발생하지 않는다.


2. let


let은 ES6(ECMAScript2015)부터 등장한 변수 선언 키워드로
var보다 엄한 규칙을 가지고 있어 var에서 발생하던 문제들이 해결되었다.

1. 재선언 : 불가 / 재할당 : 가능

let one = "a";
console.log(one); 	//결과 a
//
let one;		//결과 에러발생
//
one = "b";		//결과 에러발생 X
console.log(one); 	//결과 b

let은 var과 달리 같은 이름으로 같은 스코프 내에서
변수를 재선언하는 것이 불가능하다.
하지만 재할당하는 것은 가능하다.

2. 범위(Scope) : BS(Block Scope, 블록 범위)

(function() {
	if(true){
		let num = 3;
		console.log(num);	//결과 3
	}
	console.log(num);		//결과 에러발생
})();
console.log(num);			//결과 에러발생

let으로 선언한 변수는
블록 내에서만 사용 가능한 블록 범위(Block Scope)이다.

num이 속한 블록은 if문의 블록으로,
이 블록 밖에서는 num을 참조할 수 없어 에러가 발생한다.

let 역시 블록에 속해 있지 않은 곳에서 선언하면
Global Scope, 전역 변수로써 사용할 수 있다.

var의 문제점 중 하나가 함수의 내부가 아닌 곳에서 선언한다면
모두 전역변수가 되어 전역변수를 남발하게 되는 것인데,
let을 사용한다면 함수 내부가 아니더라도 블록으로 쌓여있다면
지역변수로써 사용할 수 있기에 전역변수를 남발하지 않을 수 있다.

3. 초기값 할당 필수 여부 : X

let one;	//결과 에러발생X

변수를 선언하며 초기화를 하지 않아도 에러가 발생하지 않는다.


3. const


const는 let과 함께 ES6(ECMAScript2015)부터 등장한 변수 선언 키워드로
조금 더 엄한 규칙을 가지며 상수를 선언할 때 사용한다.

1. 재선언 : 불가 / 재할당 : 불가

const one = "a";
console.log(one); 	//결과 a
//
const one;		//결과 에러발생
//
one = "b";		//결과 에러발생

const는 상수를 선언하기 위해서 사용하기 때문에
같은 범위(Scope) 내에서 재선언도, 재할당도 불가능하다.

2. 범위(Scope) : BS(Block Scope, 블록 범위)

(function() {
	if(true){
		const num = 3;
		console.log(num);	//결과 3
	}
	console.log(num);		//결과 에러발생
})();
console.log(num);			//결과 에러발생

const도 let과 마찬가지로 블록 범위(Block Scope)에 해당하기에
본인이 속한 블록 내에서만 참조가 가능하다.

const도 블록에 속해 있지 않은 곳에서 선언하면
Global Scope, 전역 변수로써 사용할 수 있다.

3. 초기값 할당 필수 여부 : O

const one;	//결과 에러발생

변수를 선언하며 초기화를 하지 않을 경우 에러가 발생한다.
반드시 선언과 동시에 초기화를 해 주어야 한다.


4. 호이스팅(Hoisting)

1) 호이스팅이란?

자바스크립트에는 호이스팅(Hoisting)이란 것이 존재한다.

호이스팅은 끌어올리기 라는 뜻을 가진 것처럼
변수들의 선언을 자신이 속한 범위 내의 최상위로 끌어올려서
선언하도록 하여 실제 선언한 위치보다 먼저 선언되도록 한다.

이러한 호이스팅은 변수 선언 키워드에 따라 다르게 적용된다.

2) var의 호이스팅

console.log(test);	//결과 undefined
var test = "test";
console.log(test);	//결과 test

var 키워드를 사용한 변수는 호이스팅되어
자신이 속한 범위의 최상위에서 선언됨과 동시에 undefined로 초기화된다.
그리고 실제로 변수의 값을 초기화하는 위치에서 값이 할당된다.

var test = undefined;
console.log(test);	//결과 undefined
test = "test";
console.log(test);	//결과 test

위의 코드가 이렇게 변하는 것이다.

최상단에서 선언과 undefined값으로 초기화가 이루어졌기 때문에
실제로 변수를 선언하기 이전부터 해당 변수를 참조해도
에러가 발생하지 않으며 undefined값을 가지고 있고
실제 선언과 초기화가 이루어지는 위치 이후부터는 정상적으로
할당된 값을 가지고 있다.

실제 값이 할당되기 전에 참조를 해도 에러가 발생하지 않아
이 또한 유지보수 상에서 문제를 유발할 수 있다.

3) let, const의 호이스팅

let test = "전역변수로 선언";
{
	console.log(test);	//결과 에러발생
	//Cannot access 'test' before initialization
	let test = "test";
	console.log(test);	//결과 test
}

let과 const는 var에서 언급한 문제를 겪지 않기 위해
변수 선언은 최상위로 끌어올리되 초기화를 하지 않는다.

let과 const가 호이스팅되지 않는다고 오해하는 경우가 있는데
만약 호이스팅이 이루어지지 않았다면
전역변수로 선언된 test가 참조되면서 에러가 발생하지 않을 것이다.

선언은 되어있되 초기화가 되어 있지 않아서
initialization(초기화)를 하기 전에 접근할 수 없다는
에러 메시지가 출력된다.

이렇게 호이스팅되어 최상단에서 선언된 변수와
실제로 변수를 선언, 할당한 사이의 영역을
TDZ(Temporal Dead Zone, 일시적 사각지대)이라고 하며,
TDZ에서 let과 const 변수를 참조 시 에러가 발생한다.

0개의 댓글