요약
- 실행 컨텍스트 생성 시 렉시컬 스코프 내의 선언이 끌어올려 지는 게 호이스팅이다.
- 실행 컨텍스트는 자바스크립트 엔진이 소스코드를 평가하고 실행하기 위해 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다.
- 렉시컬 스코프는 함수를 어디서 호출했는지가 아니라 함수를 어디서 정의했는지에 따라 상위 스코프를 결정하는 방식을 말한다.
- 스코프는 식별자가 유효한 범위를 말한다. 모든 식별자(변수명, 함수명, 클래스명 등)는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조 할 수 있는 유효 범위가 결정되는데 이를 스코프라고 부른다.
- 스코프라는 개념이 없다면 같은 이름을 갖는 변수는 충돌을 일으키게 되므로 프로그램 전체에서 하나밖에 사용할수 없게 된다는 문제가 발생한다.
- 렉시컬 환경은 스코프를 구분하여 식별자를 등록하고 관리하는 저장소 역할을 하는 렉시컬 스코프의 실체다.
호이스팅
console.log(score); // undefined var score; // 변수 선언문
자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기(런타임)에 앞서 먼저 소스코드의 평가 과정을 거치면서 소스코드를 실행하기 위한 준비를 한다.
소스코드의 평가과정에서 자바스크립트 엔진은 변수 선언을 포함한 모든 선언문(변수 선언문, 함수 선언문)을 소스코드에서 찾아내 먼저 실행한다.
소스코드의 평가 과정이 끝나면 비로소 변수 선언을 포함한 모든 선언문을 제외하고 소스코드를 한줄씩 순차적으로 실행한다.
이 과정에서 선언문이 코드의 선두(정확하게 말하면 스코프의 선두)로 끌어올려진것처럼 동작하는 자바스크립트 고유의 특징을 호이스팅이라고 부른다.
함수 선언문과 함수 표현식의 호이스팅
함수 선언문은 호이스팅이 가능하지만 함수 표현식은 호이스팅이 불가능하다.
함수 선언문으로 정의한 함수와 함수 표현식으로 정의한 함수의 생성 시점이 다르다.
함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는것이 아니라 변수 호이스팅이 발생한다.
함수 표현식 이전에 함수를 참조하면 undefined로 평가되므로 undefined를 호출하는 결과가 발생해 타입 에러가 발생하게 된다.
호이스팅과 스코프의 관계
호이스팅은 스코프 단위로 동작한다.
호이스팅은 변수 선언이 스코프의 선두로 끌어 올려진 것처럼 동작하는 자바 스크립트 고유의 특징을 말한다.
- 전역 변수의 호이스팅은 전역 변수의 선언이 전역 스코프의 선두로 끌어 올려진것 처럼 동작하는것을 말한다.
- 지역 변수의 호이스팅은 지역 변수의 선언이 지역 스코프의 선두로 끌어 올려진것 처럼 동작하는것을 말한다.
var, let의 호이스팅 관계
- var 키워드로 선언한 변수는 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계와 초기화 단계가 한번에 진행된다.
- 선언단계에서 스코프(실행 컨텍스트의 렉시컬 환경)에 변수 식별자를 등록, 자바 스크립트 엔진에 변수의 존재를 알린다.
- 초기화 단계에서 undefined로 변수를 초기화한다. → 따라서 변수 선언문 이전에 변수에 접근해도 에러가 발생하지 않는다.
- let 키워드로 선언한 변수는 선언 단계와 초기화 단계가 분리되어 진행된다.
- 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언단계가 실행된다.
- 초기화 단계는 변수 선언문에 도달했을때 실행된다. → 참조 에러가 발생하게 된다.
- 스코프의 시작 지점부터 초기화 단계 시작 지점(변수 선언문)까지 변수를 참조 할수 없다.
- 스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할수없는 구간을 일시적 사각지대라고 부른다.
- 중요한점은 ES6에서 도입된 let, const를 포함해서 모든 선언은 호이스팅을 한다. 단, let, const, class를 사용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다.
참고
모던 자바 스크립트 딥다이브 p_42 변수 호이스팅
모던 자바 스크립트 딥다이브 P_164 함수 호이스팅
모던 자바 스크립트 딥다이브 P_200 변수의 생명주기
모던 자바 스크립트 딥다이브 p_212 변수 호이스팅 var, let, const