var, let, const에 대한 정리

Shim.SeongHo·2021년 2월 9일
1

[JavaScript]

목록 보기
1/15
post-thumbnail

var, let, const에 대한 정리


1. var

자바스크립트 es5 버전까지의 변수 선언 방식이었다.

var 키워드는 생략 가능하다.

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

재선언과 재할당이 모두 가능하다.

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

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

a = "30";
console.log(a); //30

var키워드는 함수 레벨 스코프(function level scope)이다.

자바스크립트는 다른 언어(java, c)와 달리 기본적으로 블록 레벨 스코프(block level scope)가 아니라 function level scope이다.
function level scope란 함수 안에서 사용하면 함수 밖을 제외한 내부 어디서든 접근이 가능하고 함수 외부에서 선언된 모든 변수는 전역 변수로 한다는 뜻이다.

function f() {
  var hello = "hello world";
  console.log(hello);
}
f(); // hello world
console.log(hello); // ReferenceError

hellovar로 선언된 function level scope이기 때문에 함수 외부에서 hello에 접근하면 ReferenceError가 발생한다.
전역 변수의 사용은 변수 이름이 중복될 수 있고, 의도치 않은 재할당에 의한 상태 변화로 코드를 예측하기 어렵게 만들 수 있으므로 사용을 지양해야 한다. 이러한 문제점들을 해결하기 위해 es6부터는 letconst의 도입으로 block level scope를 사용할 수 있게 해준다.

2. let, const

재선언은 let, const 둘 다 불가능하다.

let a = 10;
let a = 20; // SyntaxError
const b = 10;
const b = 20; // SyntaxError

재할당은 let은 가능하지만 const는 불가능하다.

let a = 10;
a = 20;
console.log(a); // 20
const b = 10;
b = 20;
console.log(b); // TypeError

let, const는 블록 레벨 스코프(block level scope)이다.

block level scope란 모든 코드 블록(함수, if문, for문, while문, try/catch문 등..)내에서 선언된 변수는 코드 블록 내에서만 유효하며 코드 블록 외부에서는 참조할 수 없다. 즉, 코드 블록 내부에서 선언한 변수는 지역 변수이다.

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

let 키워드는 해당 블록 안에서만 유효하기 때문에 ReferenceError가 출력된다. (const도 마찬가지)

3. 호이스팅

호이스팅(Hoisting) : 스코프 안의 어디에서든 변수 선언은 해당 스코프의 최상위에서 선언된 것과 동등하다.

그 전에 잠깐 변수의 생성 단계를 보자면, 변수는 3단계의 생성 과정을 거친다.

선언 단계 : 변수를 실행 컨텍스트의 변수 객체에 등록한다. 이 변수 객체는 스코프가 참조하는 대상이 된다.
초기화 단계 : 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보한다. 이 단계에서는 변수는 undefined로 초기화된다.
할당 단계 : undefined로 초기화된 변수에 실제 값을 할당한다.

var키워드로 변수를 생성하면 선언 단계와 초기화 단계가 동시에 이루어진다.

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

아래의 코드와 위의 코드는 같다.

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

이 코드에서 a가 선언과 초기화가 동시에 이루어지기 때문에 undefined가 출력되는 것이다.

var a = 10;
function f() {
  console.log(a); // undefined
  var a = 20;
  console.log(a); // 20
}
f();

실제로는 이런식으로 동작하는 것이다.

var a = 10;
function f() {
  var a; // hosting
  console.log(a); // undefined
  a = 20;
  console.log(a); // 20
}
f();

let, const키워드에서 호이스팅은 조금 다르다.

let은 선언과 초기화가 분리되어 진행되는데, 스코프에 변수를 등록하지만 초기화 단계는 변수 선언문에 도달했을 때 이루어진다.hoisting이 되면 스코프 최상단에서 선언이 진행되고 초기화는 되지 않았기 때문에 ReferenceError가 뜬다.

console.log(a); // ReferenceError
let a = 10; // 변수 선언문에서 초기화 단계 실행

스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다. 스코프의 시작 지점부터 초기화 시작 지점까지의 구간을 일시적 사각지대TDZ(Temporal Dead Zone)라고 한다.
letconstTDZ의 영향을 받는 구문들이다.

// 					TDZ
console.log(a); // ReferenceError	TDZ
let a = 10;										
// 					TDZ
console.log(a); // ReferenceError	TDZ
const a = 10;

위의 코드 hoisting을 수행하지만 초기화되기 전에 참조를 해서 ReferenceError가 출력된다.

4. var vs let vs const

변수 선언에는 기본적으로 const를 사용하고 let은 재할당이 필요한 경우에 사용하는 것이 좋다. const 키워드를 사용하면 의도치 않는 재할당을 방지해 주기 때문에 보다 안전하다.

  1. 재할당이 필요한 경우에 한정해서 let을 사용한다. 이때 변수의 스코프는 최대한 좁게 만든다.
  2. 변경이 발생하지 않는 상수와 객체에는 const를 사용한다.

5. 참고

https://ui.toast.com/weekly-pick/ko_20191014
https://poiemaweb.com/es6-block-scope

profile
알아가는 재미

0개의 댓글