IT/면접

프론트엔드 개발자 면접 질문(기술면접)(4) - 호이스팅

뀨뿌뀨뿌 2022. 2. 12. 17:08

자바스크립트 호이스팅

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것

호이스팅(Hoisiting)

  • 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언(코드 실행하기 전 변수 선언/함수 선언이 해당 스코프 최상단으로 끌어 올려짐)
    =>자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑고, 함수 안에 존재하는 변수/함수 선언에 대한 정보를 기억하고 있다가 실행됨. 유효범위는 함수 블록 안에서 유효
  • 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것
    => 실제로 코드가 끌어올려지는 건 아니고, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이고 실제 메모리에 변화는 없음
  • 코드 실행 전 이미 변수 선언/함수 선언이 저장되어 있기 때문에 선언문보다 참조/호출이 먼저 나와도 오류 없이 동작(var 키워드로 선언한 변수와 함수 선언문일 경우 오류 없이 동작)

변수 호이스팅(var, let, const 키워드)

  • 자바스크립트의 모든 선언에는 호이스팅이 일어남
  • let, const, class를 이용한 선언문은 호이스팅이 발생하지 않은 것처럼 동작
  • var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생
  • let, const 키워드로 선언된 변수는 스코프 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문
  • 호이스팅이라는 용어가 '선언이 먼저 메모리에 저장되었다'를 의미하기 때문에 '선언이 끌어올려진다'라는 의미이기 때문에 모든 선언은 호이스팅이 일어난다는 말은 참이 됨
    => 호이스팅이 파일의 맨 위로 끌어올려진 것 같은 현상을 의미할 때 선언문 이전에 참조해서 에러를 발생시킨다고 호이스팅이 일어나지 않은 것은 아니라는 의미
  • let, const 키워드 오류가 나는 이유는 var 키워드는 선언과 함께 undefined로 초기화되어 메모리에 저장되는데 let과 const는 초기화되지 않은 상태로 선언만 메모리에 저장되기 때문
    => 초기화되지 않으면 변수를 참조할 수 없기 때문에 참조 에러를 일으킴. 호이스팅이 일어나지 않으면 에러가 발생하지 않음

변수 생성될때 호이스팅 순서

  • 변수는 3단계에 걸쳐 생성됨
  • 1단계 - 선언 단계(Declaration phase)
    • 변수를 실행 컨텍스트의 변수 객체에 등록
    • 이 변수 객체는 스코프가 참조하는 대상이 됨
  • 2단계 - 초가화 단계(Initialization phase)
    • 변수 객체에 등록된 변수를 위한 공간을 메모리에 확보
    • 이 단계에서 변수는 undefined로 초기화됨
  • 3단계 - 할당 단계(Assignment phase)
    • undefined로 초기화된 변수에 실제 값을 할당
  • var 키워드로 선언한 변수는 선언 단계와 초기화 단계가 한 번에 이뤄짐. 스코프에 변수를 등록하고 메모리에 변수를 위한 공간을 확보한 후, undefined로 초기화함.
    => 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않지만 undefined를 반환하고 변수 할당문에 도달하면 값이 할당됨.
  • let, const 키워드로 선언된 변수는 선언 단계와 초기화 단계가 분리되어 진행됨. 스코프에 변수를 등록하지만 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 이후) 이뤄짐. 초기화 이전에 변수에 접근하면 아직 변수가 초기화되지 않아서 변수를 위한 메모리 공간이 아직 확보되지 않았기 때문에 참조 에러가 발생함.
    => 스코프의 시작 지범부터 초기화 시작 지점까지는 변수를 참조할 수 없음. 이 구간을 '일시적 사각지대(Temporal Dead Zone;TDZ)'라 부름.

정리

호이스팅은 자바스크립트의 코드를 해석하고 실행하는 방식 때문에 나타남.
자바스크립트는 코드를 해석하는 단계와 실행하는 단계로 나뉘고, 해석하는 단계에서 선언 문장을 초기화하면서 스코프를 형성하고 실행하는 단계에서 값을 할당하거나 계산을 하는 행위를 한다고 볼 수 있음.