[JavaScript] var, let, const 의 차이 - 호이스팅, 스코프

D uuu·2023년 12월 12일
0

JavaScript

목록 보기
1/8

var, let, const 의 차이점

1. 중복 선언

var 는 중복해서 변수를 선언해도 에러 없이 다른 값이 출력 된다.
기존에 선언했던 변수의 존재를 까먹고 값을 재할당하게 되는 등 개발자가 실수 하기가 쉽다는 단점이 있다.

var

var number = 1;
console.log(number) /// 1

var number = 5;
console.log(number) /// 5

let 과 const 는 중복 선언이 불가능하다. 이미 선언한 변수를 다시 선언할 경우 아래와 같이 에러가 발생해 var 에 비해서 코드의 안전성을 높여준다.

let

let number = 1;
console.log(number) /// 1

let number = 5;  /// SyntaxError: Identifier 'number' has already been declared

const

const number = 1;
const number = 5;  /// SyntaxError: Identifier 'number' has already been declared


2. 스코프(scope)

스코프란 변수를 참조할 수 있는 범위를 뜻한다. 여기서도 var 로 선언한 변수와 let, const 로 선언한 변수의 스코프가 다르다.
var 는 함수 레벨 스코프를 지원한다.

var : 함수 레벨 스코프

<foo 함수 내부에서 var 변수>

function foo() {
	var number = 1;
    console.log(number)
 }
 
 foo()  ///  1
 
 console.log(number)  /// ReferenceError : number is not defined

<if문 내부에서 var 변수>

if(true) {
	var number = 1;
    console.log(number) /// 1
}

console.log(number) /// 1

함수 내부에서 선언된 변수만 지역변수로 한정하며 나머지는 모두 전역변수로 간주한다. foo 함수 안에 var 변수는 지역 변수로 간주하여 외부에서 콘솔을 찍었을때 참조 에러가 발생하는 반면, if문 안에서 선언 된 var 변수는 전역변수로 간주하여 외부에서도 접근이 가능하다. 이로 인해 의도치 않게 전역 변수가 선언되어 심각한 부작용이 발생하기도 한다.

let, const : 블록 레벨 스코프

let 과 const 는 함수 내부는 물론이며 if, for(반복문) 등의 코드 블록 { } 안에 선언된 변수도 지역변수 취급한다.

if(true) {
	let number = 1;
    console.log(number) /// 1
}

console.log(number)   /// ReferenceError : number is not defined

정리 : var 는 함수 내부에서만 선언 된 변수만 지역변수로 인정하는 함수 레벨 스코프이고, let, const 는 블록 내부{ } 에서 선언된 변수까지도 지역변수로 인정하는 블록 레벨 스코프이다.



3. 호이스팅

자바스크립트는 코드를 실행에 앞서 변수, 함수 등의 선언문만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 scope 에 등록하는 평과 과정을 거치는데, 따라서 코드가 실제로 실행되기도 전에 자바스크립트는 이미 변수의 존재를 알고 있다고 할 수 있다.

이는 마치 선언부를 코드의 최상단으로 끌어올리는 것처럼 보인다 해서 호이스팅이라고 부르는데, 여기서 var 와 let, const 도 호이스팅 과정이 다르다.

var : 변수 호이스팅 발생

console.log(number) /// undefined

var number = 1;

console.log(number) /// 1

number 가 선언되기 전에 참조 되었음에도 불구하고 에러가 발생하지 않고 undefined 가 나온다. 코드 실행 전에 자바스크립트 내부에서 선언문을 평가하는 과정에서 var number 변수를 미리 선언하고 undefined 로 초기화 해두었기 때문이다.

let, const : TDZ(Temporal Dead Zone) 발생

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

let number = 1;

console.log(number) /// 1

let, const 를 사용해 변수를 선언할 경우, 마찬가지로 코드 실행에 앞서 변수, 함수 등의 선언문만 먼저 실행하는 평가 과정을 거치지만, 초기화는 이뤄지지 않는다. let, const 의 경우엔 실행시점에서 실제 선언부를 만날때 초기화가 이뤄진다. 따라서 참조할 값이 없기 때문에 참조 에러가 발생한다.

핵심
var, let, const, 함수, class 등 모든 선언부는 자바스크립트에서 호이스팅 된다. 실제 코드가 실행되기 전에 선언부의 식별자를 스코프에 등록하는 과정(평가과정) 을 거치기 때문이다. 그러나 변수는 할당된 값은 저장되지 않는다. 즉, let name="seo" 에서 name 이라는 변수명은 스코프에 등록되지만 name 의 값이 seo 라는 것은 평가과정에서 모른다. 그러나 var name='seo' 로 선언할 경우엔 name 이라는 변수명을 등록하고, undefined 로 값을 초기화 시킨다.
따라서 var, let, const 는 모두 호이스팅이 일어나지만 초기화가 과정이 다르기 때문에 결과가 다른 것 이다.



정리

최대한 전역 변수보다는 지역 변수를 활용하는 것을 권장한다. 협업을 하다보면 우연히 같은 변수 이름을 사용할 경우, 변수를 덮어 쓰게 되는 불상사가 발생할 수도 있고, 여기저기서 전역 변수를 가져다 쓸 경우, 개발자가 예상한 값과는 완전히 다른 값이 나올 수도 있다.

따라서 기본적으로 변수의 스코프는 최대한 좁게 만들어 관리하는 편이 좋다. var 보다는 let 과 const 키워드를 사용하고, 변하지 않는 값(상수) 이라면 let 보다는 const 키워드를 사용하는 편이 안전하다.

profile
배우고 느낀 걸 기록하는 공간

0개의 댓글