본문으로 건너뛰기
yceffort
PostsSeriesTagsAbout🧪 Research
EN

Tweaks

theme
accent palette
film grain
minimal mode
BACK TO INDEX
◆ ESSAY
--min
--year
KOoriginal

mailMail icongithubtwitter
yceffort
•
© 2026
•
https://yceffort.kr
BACK TO INDEX
◆ ESSAY

var let const, 그리고 호이스팅

avatar
yceffort
2020-05-20 · 6분
6min
2020year
KOoriginal
javascript

var let const, 그리고 호이스팅

var

우리가 모두 아는 var 키워드는 아래와 같은 특징을 가지고 있다.

  1. 함수레벨 스코프를 가지고 있다.

    대부분의 프로그래밍 언어들이 블록 레벨 스코프를 사용하고 있지만, var로 선언된 키워드는 함수레벨 스코프를 갖는다.

    var name = 'hello'
    
    function t() {
      var name = 'hi'
      console.log(name) // hi
    }
    
    t()
    console.log(name) // hello
    
  2. var 키워드는 생략이 가능하다.

    생략이 가능하기 때문에, 함수가 선언한 환경의 this에 영향을 받는다. 일반적인 웹 환경에서는 window일 것이다.

  3. 중복 선언이 가능하다.

    var name = 'hello'
    var name = 'hi'
    console.log(name) // hi
    
  4. 호이스팅 당한다.

    호이스팅이란

    스코프 안에 있는 선언들을 모두 스코프의 최상위로 끌어올리는 것

    이다. 자바스크립트 인터프리터가 코드를 해석할 때 함수의 선언, 할당, 실행을 모두 나눠서 처리하기 때문이다. 예를 들어보자.

    console.log(name) // undefined
    var name = 'hello'
    

    이 코드는 참조 에러가 나지 않고, undefined를 리턴한다. 그 이유는 자바스크립트가 호이스팅을 하면서 아래와 같은 방식으로 코드를 해석하기 때문이다.

    var name // undefined
    console.log(name)
    name = 'hello'
    

2. let

let은 es6에서 가장 잘 알려진 기능 중 하나다. var랑 비슷한 것 같지만, 사실 몇가지 다른 점이 있다.

  1. 블록 수준 스코프를 가지고 있다.

    아래의 예를 살펴보자.

    {
      {
        {
          var name = 'hello'
        }
      }
    }
    console.log(name) // hello
    
    {
      {
        {
          let name2 = 'hi'
        }
      }
    }
    console.log(name2) // ReferenceError: name2 is not defined
    

    let과 const는 모두 블록 수준의 스코프를 사용 하고 있다. 따라서 블록 내부에서 선언한 변수는 모두 지역변수로 취급된다. 때문에 블록 내부에서 선언한 변수들을 참고할 수가 없다.

  2. 키워드 생략이 불가능하다.

    키워드를 생략하면 var처럼 작동하게 된다.

  3. 중복선언이 불가능하다.

    그렇다.

  4. 호이스팅 당한다.

    가끔 인터넷을 뒤지다보면, let과 const는 호이스팅 당하지 않는다는 이야기가 있는데, 이는 잘못된 사실이다. 두 키워드 모두 호이스팅 당하기는 마찬가지이다.

    이것을 이해하기 위해서는, Temporary Dead Zone에 대해 알아야 한다.

Temporary Dead Zone

아래 코드를 살펴보자.

name = 'hello' // ReferenceError: Cannot access 'name' before initialization
let name = 'hi'

자. 만약 name이 호이스팅 되지 않았다면, 두 번째 let선언에서 already declared에러가 났었어야 했다. 근데 현실은 초기화 하기전에 엑세스 할 수 없다는 에러를 내뱉었다.

아래 코드는 어떨까?

function sayHello() {
  return name
}
let name = 'hi'
console.log(sayHello()) // hi

별탈없이 hi를 내뱉은 것을 볼 수 있다. 그 말인 즉, name이 분명 호이스팅 되었다는 뜻이다.

다른 이야기로 넘어가서, 자바스크립트에서는 총 3단계에 걸쳐서 변수를 생성한다.

  1. 선언(Declaration): 스코프와 변수 객체가 생성되고, 스코프가 변수 객체를 참조한다.
  2. 초기화(Initialization): 변수 객체 값을 위한 공간을 메모리에 할당한다. 이 때 할당되는 값은 undefined다.
  3. 할당(Assignment): 변수 객체에 값을 할당한다.

var는 선언과 동시에 초기화가 이루어진다. 즉, 선언과 동시에 undefined가 할당된다.

그러나 let과 const는 다르다. 선언만 될뿐, 초기화가 이루어지지 않는다. 바로 이단계에서 TDZ에 들어가게 되는 것이다. 즉, 선언은 되어있지만, 초기화가 되지 않아 이를 위한 자리가 메모리에 준비되어 있지 않은 상태라는 것이다.

const

const에서 구별되는 특징만 몇가지 살펴보자.

  1. const는 초기화와 동시에 선언이 이루어져야 한다.

    let hello
    hello = 'hello'
    
    const hi //SyntaxError: Missing initializer in const declaration
    hi = 'hi'
    
  2. const 자체가 값을 불변으로 만드는 것이 아니다.

    아래 코드는 당연히 안된다.

    const hello = 'hello'
    hello = 'hi' // TypeError: Assignment to constant variable.
    

    그렇다고 이것도 안되는 것은 아니다.

    const hello = ['hi']
    hello.push('hello')
    
    const hello = 'hello'
    var hi = hello
    hi = 'hi'
    console.log(hello) // hello
    console.log(hi) // hi
    

    객체 자체를 동결시키기 위해서는 Object.freeze를 사용하면 된다.

  3. 상수를 선언할 때 사용한다.

결론

  • 호이스팅은 변수의 선언을 최상단에 끌어올린다는 뜻이다.
  • var let const는 모두 호이스팅 된다.
  • let 선언과 동시에 TDZ에 들어가서 초기화가 필요한 별도의 상태로 관리된다.
  • const 는 선언과 동시에 초기화, 할당까지 이루어진다.
  • var는 왠만하면 쓰지말자
  • let대신 const를 사용하자. let으로 선언되어 있다면, 어디선가 이 변수가 바뀔지도 모른다는 생각을 가지고 있어야 하므로, 코드를 읽기가 어려워진다. 반면 const는 초기화, 선언, 할당까지 되어 있으니 변경되지 않을 것이다라는 확신으로 코드를 볼 수 있다. (물론 객체의 속성은 바뀔 수 있음.)

관련 글

  • #javascript

    Javascript Execution Context

    들어가기에 앞서 더 좋고 제가 많이 참고한 글이 [여기](https://poiemaweb.com/js-execution-context)에 있습니다. 이글을 보시는게 낫습니다. ```toc tight: true, from-heading: 1 to-heading: 4 ``` # 자바스크립트 실행컨텍스트 이번 포스팅으로 자바스크립트 실행 컨텍스트에 대해 온...

    2020-06-26·17분
  • #javascript

    javascript 일반 함수와 화살표 함수의 차이

    ES6에서부터 생긴 `arrow function`은 일반적으로 `()=>{}`의 모양을 하고 있으며, 동작도 비슷해보인다. 하지만 이 두 선언방식은 두가지 분명한 차이를 가지고 있다. 하지만 그전에 this를 알아야 한다.

    2020-05-19·3분
  • #javascript

    자바스크립트 함수를 선언하는 여섯가지 방법

    거의 모든 것이라고 했지만 사실 그렇진 않음 어그로임

    2020-10-22·4분
  • #javascript

    null과 undefined의 차이, 그리고 역사

    이런 것 또한 매력이라면 매력이 아니다

    2021-02-02·4분

새 글을 놓치고 싶지 않으시다면

RSS로 구독해 주세요.

RSS 구독 →

yceffort — 프론트엔드 엔지니어입니다.

← Back to the blogIssue on GitHub →