2025. 6. 2. 09:00ㆍJavascript/Javascript
변수의 생성 과정은 아래의 3단계를 거친다.
- 선언 단계
- 초기화 단계
- 할당 단계
그리고 var, let, const는 각각 아래의 과정을 통해 생성된다.
var의 생성 과정
- 선언 및 초기화 단계
- 할당 단계
let의 생성 과정
- 선언 단계
- 초기화 단계
- 할당 단계
const의 생성 과정
- 선언 + 초기화 + 할당
let, const, var의 차이점 5가지
- 중복 선언 가능 여부
- 재할당 가능 여부
- 변수 스코프의 유효 범위
- 변수 호이스팅 방식
- 전역 객체 프로퍼티 여부
1. 중복 선언 가능 여부
먼저 var의 경우 중복해서 선언 및 초기화가 가능하며 중복 선언이 되는 경우 마지막에 할당된 값이 변수에 저장된다. 따라서 개발자의 입장에서는 기존에 선언해 둔 변수의 존재를 잊고 값을 재할당하는 실수를 일으키기 쉽다.
let과 const의 경우 중복 선언이 불가능하다. 따라서 이미 선언한 변수를 다시 선언할 경우 에러가 발생한다. var에 비해 코드의 안정성을 높여 줄 수 있는 방식으로 자바스크립트 외에 다른 언어를 쓰던 개발자들에게도 익숙하다.
2. 재할당 가능 여부
var와 let은 값의 재할당이 가능한 변수다. 변수 선언 및 초기화 이후에 반복하여 다른 값을 재할당시킬 수 있다.
반면 const의 경우 값의 재할당이 불가능한 상수이다. const는 상수를 선언하는 키워드로 처음에 선언 및 초기화하고 나면 다른 값을 재할당할 수 없다. var나 let과는 달리 const 선언에서는 반드시 값을 선언하는 것과 동시에 정의해야 한다.
그러므로 재할당이 필요 없는 경우 const를 사용해 불필요한 변수의 재사용을 방지하고, 재할당이 필요한 경우 let을 사용하는 것이 좋다.
3. 변수 스코프의 유효 범위
스코프(scope)란 유효한 참조 범위를 말한다. 예를 들어 함수 내부에서 선언된 변수는 함수 내부에서만 참조가 가능한 것.
[Javascript] Scope
이번에는 자바스크립트의 Scope에 대해 알아보려 한다. Scope는 변수 또는 함수를 선언할 때 해당 변수/함수의 유효 범위를 의미한다. Scope에는 총 3가지 종류가 있다. 1. Global (전역) Scope: 코드의 모
developing-move.tistory.com
자바스크립트에서는 var로 선언한 변수의 스코프와 let, const로 선언한 변수의 스코프가 다르다.
var는 함수 레벨의 스코프(function-level scope)를 갖는다. 함수 내부에 선언된 변수만 지역 변수로 한정하며 나머지는 모두 전역 변수로 간주한다. 자바스크립트에서는 if문, for문, while문, try/catch문 등의 코드 블록 {...} 내부에서 var로 선언된 변수를 전역 변수로 간주한다. 따라서 var로 선언된 변수는 블록 외부에서도 어디에서나 참조할 수 있다.
반면 let과 const는 블록 레벨 스코프(block-level scope)를 갖는다. let, const는 함수 내부는 물론 if문이나 for문 등의 코드 블록 {...}에서 선언된 변수도 지역 변수로 취급한다. 당연히 함수 내부에서 선언된 변수도 외부에서 참조할 수 없다.
정리하자면 var는 함수 내부에 선언된 변수만 지역 변수로 인정하는 함수 레벨 스코프이고 let, const는 모든 블록 내부에서 선언된 변수까지 지역 변수로 인정하는 블록 레벨 스코프인 것이다.
4. 변수의 호이스팅 방식
자바스크립트는 코드를 실행하기 전 일종의 코드 평과 가정을 거치는데 이때 변수 선언문을 미리 실행해 두기 때문에 뒤에서 선언된 변수도 앞의 코드에서 참조할 수 있게 된다. 이를 변수의 호이스팅이라고 한다.
var는 변수 호이스팅이 발생한다.
console.log(a); // undefined
var a = 10;
console.log(a); // 10
따라서 뒤에서 선언된 변수 a가 앞에서 console.log(a)의 형태로 참조되었음에도 에러를 발생시키지 않는다.
코드를 실행하기 전에 자바스크립트 엔진이 미리
1) 변수를 선언하고,
2) undefined로 초기화해 두었기 때문이다.
이를 코드로 표현하자면 아래와 같다.
var a = undefined;
console.log(a); // undefined
a = 10;
console.log(a); // 10
이것이 바로 var로 선언된 변수의 호이스팅이다.
let, const의 경우에도 변수 호이스팅이 발생한다. 하지만 var와는 다른 방식으로 작동한다.
console.log(a); // ReferenceError: a is not defined
let a = 10;
위 예시에서는 뒤에서 선언된 변수를 앞에서 참조하려 하니 에러가 발생한다. 이렇게 보면 마치 호이스팅이 발생하지 않는 것처럼 보인다. 이런 현상이 발생하는 이유는 let과 const의 호이스팅 과정이 var와는 다르게 진행되기 때문이다.
let/const로 변수를 선언하는 경우 코드 실행 전에는
1) 변수만 선언해 두며,
2) 초기화는 코드 실행 과정에서 변수 선언문을 만났을 때 수행한다.
let a; // 선언만 하고 정의는 하지 않음. var는 정의하지 않아도 undefined가 들어감.
console.log(a); // ReferenceError: a is not defined
a = 10;
console.log(a); // 10
그래서 호이스팅이 발생하기는 하지만 값을 참조할 수 없어서 호이스팅이 발생하지 않는 것처럼 보이는 것이다.
그렇다면 호이스팅이 발생하는 걸 어떻게 확인할 수 있을까?
let a = 10; // 전역변수 a선언
if(true){
console.log(a); // 10
}
위 코드는 전역 변수로 선언된 a의 값 10을 if문 블록에서 참조하여 출력하고 있다.
let a = 10; // 전역변수 a선언
if(true){
console.log(a); // ReferenceError: a is not defined
let a = 20; // 지역변수 a 선언
}
그리고 위에서는 if문 블록 내부에서 지역변수 a를 다시 선언했다. 이 경우 전역 변수 a가 있음에도 지역변수 a 앞에서 console.log()로 참조 시 에러가 발생한다. 지역 변수 a가 호이스팅되면서 TDZ(Temporal Dead Zone) 구간이 만들어졌기 때문이다.
cf. 변수의 선언과 초기화 사이에 일시적으로 변수 값을 참조할 수 없는 구간을 TDZ(Temporal Dead Zone)라고 한다.
참고로 지역 변수가 전역 변수보다 우선 순위를 갖는다.
5. 번역 객체 프로퍼티 여부
keyword | const | let | var |
global scope | NO | NO | YES |
function scope | YES | YES | YES |
block scope | YES | YES | NO |
can be reassigned | NO | YES | YES |
var a = 10;
console.log(window.a); // 10
console.log(a); // 10
var로 선언된 변수는 전역 객체(브라우저 환경일 경우 window)의 프로퍼티이다. 브라우저 환경(크롬 콘솔 등)에서 위 코드를 실행 시 var로 선언한 변수 a는 브라우저 전역 객체인 window의 프로퍼티로 할당된다.
반면 let/const로 선언된 변수는 전역 객체 프로퍼티가 아니다.
let a = 10;
console.log(window.a); // undefined
console.log(a); // 10
따라서 브라우저 환경(크롬 콘솔 등)에서 위 코드를 실행하면 let이나 const로 선언한 변수 a는 브라우저 전역 객체인 window의 프로퍼티로 할당되지 않음을 확인할 수 있다.
결론
- let과 const를 이용해서 변수를 선언하자.
- 값을 재할당시키는 경우가 아니라면 const를 디폴트로 사용하자.
- var는 절대로 사용하지 말자.
'Javascript > Javascript' 카테고리의 다른 글
[Javascript] 객체와 참조 값 (1) | 2025.06.05 |
---|---|
[Javascript] 객체(Object) (1) | 2025.06.04 |
[Javascipt] ECMAScript 2015(ES6) 그 이후 - (3) 클래스, 프로미스, 정규식 (1) | 2025.05.29 |
[Javascipt] ECMAScript 2015(ES6) 그 이후 - (2) 문자열, 배열, 객체 (1) | 2025.05.28 |
[Javascipt] ECMAScript 2015(ES6) 그 이후 - (1) 연산자 (2) | 2025.05.27 |