[JS]변수 선언 방식의 차이: var, let, const

frankiethefrank·2021년 9월 14일
0

TIL

목록 보기
2/4

자바스크립트 변수 선언은 var로만 가능했지만 ES6(ES2015)부터 let과 const가 추가되었다.

예전의 var가 let(변수), const(상수)로 분리되었다 생각할 수 있으나, 내부 사정은 상당히 다르다.

var, let, const 차이점 5가지

1. 중복선언 가능 여부
2. 재할당 가능 여부
3. 변수 스코프 유효범위
4. 변수 호이스팅 방식
5. 전역객체 프로퍼티 여부

#1. 중복 선언

1. var - 중복 선언이 가능하다

// 첫번째 변수 선언 + 초기화
var a = 10;
console.log(a); // 10

// 두번째 변수 선언 + 초기화
var a = 20;
console.log(a); // 20

// 세번째 변수 선언(초기화X)
var a;
console.log(a); // 20

var로 선언한 변수는 중복해서 선언(+초기화)이 가능
이 경우, 마지막에 할당된 값이 변수에 저장된다.

단, 초기화 없이 선언만 한 경우에는 선언문 자체가 무시된다.(에러발생X)

기존에 선언해 둔 변수의 존재를 까먹고, 값을 재할당하게 되는 등 실수 발생 가능성 有

2. const, let - 중복 선언 불가능

// let 중복 선언
let a = 10;
let a = 20; // SyntaxError: Identifier 'a' has already been declared

// const 중복 선언
const b = 10;
const b = 20; // SyntaxError: Identifier 'b' has already been declared

let, const로 선언한 변수는 중복 선언이 불가능하다.
코드에서 보는 것처럼 이미 선언한 변수를 다시 선언할 경우, 에러가 발생한다.
var에 비해서 코드의 안정성을 높여줄 수 있는 방식

2. 재할당

1. var, let - 값의 재할당이 '가능'한 변수

var a = 10;
a = 20;
console.log(a); // 20

let b = 111;
b = 222;
console.log(b); // 222

var와 let은 변수를 선언하는 키워드.
변수 선언 및 초기화 이후에 반복해서 다른 값을 재할당 할 수 있다.

2. const - 값의 재할당이 '불가능'한 상수

const c = 111;
c = 222; // TypeError: Assignment to constant variable.

const는 상수를 선언하는 키워드다.
처음에 선언 및 초기화하고 나면 다른 값을 재할당 할 수 없다.

*const는 처음 선언할 때 반드시 초기화(값 할당)를 해줘야한다.

const a = 10;
const b; // SyntaxError: Missing initializer in const declaration

3. 스코프(scope)

스코프란? 유효한 참조 범위
예를 들어, 함수 내부에서 선언된 변수는 함수 내부에서만 참조가 가능하다.
이 경우 변수의 스코프는 함수 내부로 한정된다.

자바스크립트는 var로 선언한 변수의 스코프와 let, const로 선언한 변수의 스코프가 다르다.

1. var - 함수레벨 스코프(function-level scope)

var는 함수 내부에 선언된 변수만 지역변수로 한정하며, 나머지는 모두 전역변수로 간주한다.

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

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

hello 함수 내부에서 선언된 a 변수는 함수 내부에서만 참조가 가능하며, 외부에서 참조 시 에러가 발생한다.

하지만, 함수를 제외한 영역에서 var로 선언한 변수는 '전역변수'로 취급된다.

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

console.log(a); // 10

자바스크립트에서는 if, for, while, try/catch문 등의 코드 블럭{...}내부에서 var로 선언된 변수를 전역 변수로 간주한다.
그래서 블럭 외부에서도 어디에서나 참조할 수 있다.

그러나 let과 const는 다르다.

2. let, const - 블록 레벨 스코프(block-level scope)

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

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

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

if문의 블럭 내부에서 let으로 선언된 변수는 외부에서 참조되지 않음을 알 수 있다.

당연히 함수 내부에서 선언된 변수도 외부에서 참조할 수 없다.

function hello() {
	let a = 10;
    console.log(a); // 10
}

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

정리하자면, var는 함수 내부에 선언된 변수만 지역변수로 인정하는 함수 레벨 스코프
let, const는 블록 내부에서 선언된 변수까지도 지역변수로 인정하는 블록 레벨 스코프
*참고로, 블록은 if문이나 for문 등에서 중괄호{}로 둘러싸인 코드 영역

4. 호이스팅

자바스크립트는 코드를 실행하기 전, 일종의 '코드 평가 과정'을 거치는데, 이 때 '변수 선언문'을 미리 실행해두기 때문에 뒤에서 선언된 변수도 앞의 코드에서 참조할 수 있게 된다.
이를 변수 호이스팅이라고 한다.

var와 let/const는 호이스팅 과정도 다르다.

1. var - 변수 호이스팅이 발생한다.

console.log(a); // undefined
var a = 10;
console.log(a); // 10

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

2. let, const - 변수 호이스팅이 발생한다. 하지만 다른 방식으로 작동한다.

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

뒤에서 선언된 변수를 앞에서 참조하려 하니 에러가 발생한다.
마치 호이스팅이 발생하지 않는 것처럼 보인다.

이런 현상이 발생하는 이유는 let, const의 호이스팅 과정이 var와 다르게 진행되기 때문이다.
let/ const로 변수를 선언하는 경우,
코드 실행 전에는 1)변수 선언만 해두며 2)초기화는 코드 실행 과정에서 변수 선언문을 만났을 때 수행한다.

그래서 호이스팅이 발생하기는 하지만, 값을 참조할 수 없어서 호이스팅이 발생하지 않는 것처럼 보이는 것이다.
변수 선언과 초기화 사이에 일시적으로 변수 값을 참조할 수 없는 구간을 TDZ(Temporal Dead Zone)이라고 한다.

그렇다면, 호이스팅이 발생하는 걸 어떻게 확인할 수 있을까?

아래의 두 코드를 비교해보면 알 수 있다.

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

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

이 코드는 if문 블럭 내부에서 지역변수 a를 다시 선언했다.
이 경우, 지역변수 a 앞에서 console.log()로 참조 시 에러가 발생한다.(전역변수a있어도)

왜냐하면, 지역변수 a가 호이스팅되면서 TDZ구간이 만들어졌기 때문이다.
즉, let으로 선언된 변수도 호이스팅이 발생함을 알 수 있다.
(참고로 지역변수가 전역변수보다 우선 순위를 가짐)

5. 전역객체 프로퍼티 여부

1. var - var로 선언된 변수는 전역 객체(브라우저 환경의 경우 window)의 프로퍼티다.

var a = 10;

console.log(window.a); // 10
console.log(a); // 10

브라우저 환경(크롬 콘솔 등)에서 위 코드 실행 시, var로 선언한 변수 a는 브라우저 전역 객체인 window의 프로퍼티로 할당된다.

2. let, const - let, const로 선언된 변수는 전역객체 프로퍼티가 아니다.

let a = 10;

console.log(window.a); // undefined
console.log(a); // 10;

브라우저 환경에서 위 코드 실행 시, let이나 const로 선언한 변수 a는 브라우저 전역객체인 window의 프로퍼티로 할당되지 않았음을 알 수 있다.
(window.a = undefined)

결론

1순위 - const를 최우선적으로 사용한다.

2순위 - let은 변수 값을 재할당할 필요가 있을 때만 사용한다.

3순위 - var는 ES6 이후 부터 특별한 경우를 제외하고 쓸 필요X

*참고 - 구글의 자바스크립트 스타일 가이드에 다음과 같은 문장이 있다.

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는 '절대' 사용하지 말라.
profile
hello I'm Frankie!

0개의 댓글