호이스팅(hoisting)

kimjaewon·2023년 4월 25일
0

호이스팅(hoisting)이란?

● 자바스크립트에서 변수함수 선언을 현재 스코프최상단으로 끌어 올리는 것을 말한다

● 호이스팅은 코드가 실행하기 전 변수선언/함수선언이 해당 스코프의 최상단으로 끌어 올려진 현상을 말한다

● 자바스크립트 엔진은 코드를 실행하기 전 실행 컨텍스를 위한과정에서 모든 선언(var(x), let, const, function, class)을 스코프에 등록한다

● 코드 실행 전 이미 변수선언/함수선언이 저장되어 있기 때문에 선엄문보다 참조/호출이 먼저 나와도 에러 없이 동작한다
(정확히는 var 키워드로 선언한 변수와 함수 선언문일 경우 오류 없이 동작한다 이는 선언이 파일의 맨 위로 끌어올려진 것 처럼 보이게 한다, 그래서 var 키워드는 사용x)

실행 컨텍스트는 실행 가능한 코드가 실행되기 위해 필욯한 환경을 의미하고 실행되기전 이러한 실행 컨텍스트 과정(코드를 구분하는 과정)을 거친다

그래서 자바스크립트 실행 컨텍스트에 대한 이해하는 것이 호이스팅을 이해하는데 도움이 된다 (scope, hoisting, this, function, closure 등의 동작원리를 담고 있는 자바스크립트 핵심원리이다 코드를 보고 실행 컨텍스트를 이해할 수 있어야 코드 독해, 디버깅을 할수 있다)

function example() {
console.log(x);
var x = 1;
}
example(); // 출력 결과: undefined

예를 들어 아래의 코드를 보면 변수 선언이 함수 호출보다 뒤에 있지만 호이스팅으로 인해 정상적으로 동작한다

위 코드에서 var x = 1이 실행되기 전에 console.log(x)가 실행되는데 이때 x는 아직 값이 할당되지 않았으므로 undefined가 출력된다


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

자바스크립트의 모든 선언에는 호이스팅이 일어난다

● 그런데 let, const, class를 이용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다

var 키워드로 선언된 변수와는 달리 let 키워드로 선언된 변수를 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다

● 이는 let 키워드로 선언된 변수는 스코프의 시작에서 변수의 선언까지 일시적 사각지대(Temporal Dead Zone; TDZ)에 빠지기 때문이다

여기서 중요한 지점은 이 호이스팅이라는 용어가 ‘선언이 먼저 메모리에 저장되었다.’는 것을 의미하기 때문에 즉, ‘선언이 끌어올려진다’는 의미이기 때문에 모든 선언은 호이스팅이 일어난다는 말은 참이된다.

즉, 호이스팅이 파일의 맨 위로 끌어올려진 것 같은 현상을 의미할 때 선언문 이전에 참조해서 에러를 발생시킨다고 호이스팅이 일어나지 않은 것은 아니라는 의미이다.

● 왜냐하면 정말 끌어올려진 것이 맞다(정확히는 선언이 코드 실행 전에 메모리에 저장되었다는 의미이다)

● 그런데 에러가 나는 이유는 var 키워드는 선언과 함께 nudefined로 초기화 되어 메모리에 저장되는데 let, const는 초기화 되지 않은 상태로만 선언한 메모리에 저장되기 때문이다

● 초기화 되지 않으면 변수를 참조할 수 없다 그래서 참조에러를 일으키는 것이다

let, const에도 호이스팅이 일어나기 때문에 에러를 일으키는 것이다


변수는 어떻게 생성되고 어떻게 호이스팅이 이뤄질까?

● 변수는 총 3단계에 걸쳐 생성된다

1단계: 선언 단계(Declaration phase)

● 변수를 실행하는 컨텍스트의 변수 객체를 등록한다

● 이 변수 객체는 스코프가 참조하는 대상이 된다

2단계: 초기화 단계(Initialization phase)

● 변수 객체에 등록된 변수를 위한 공간을 메로리에 확보한다

● 이 단계에서는 변수는 undefined로 초기화 된다

3단계: 할당 단계(Assignment phase)

undefined로 초기화된 변수에 실제 값을 할당한다

var 키워드로 선언한 변수는 선언 단계와 초기화 단계가 한번에 이뤄진다 즉, 스코프에 변수를 등록(선언 단계)하고 메모리에 변수를 위한 공간을 확보 후 undefined로 초기화 된다 따라서 변수 선언문 이전에 변수에 접근하여도 스코프에 변수가 존재하기 때문에 에러가 발생하지 않지만 undefined를 반환한다 이후 할당문에 도달하면 비로소 값이 할당된다

let 키워드로 선언된 변수는 선언 단계와 초기화 단계러 분리되어 진행된다 즉, 스코프에 변수를 등록(선언 단계)하지만 초기화 단계는 변수 선언문에 도달했을 때(코드 실행 후)이뤄진다 초기화 이전에 변수가 접근하려 하면 참조 에러가 발생한다 이는 아직 변수가 초기화 되지 않았기 때문이다
즉, 변수를 위한 메모리 공간이 아직 확보되지 않아스코프의 시작 지점부터 초기화 시작 지점까지는 변수를 참조할 수 없다 스코프 시작 지점부터 초기화 시작 지점까지 구간을 일시적 사각지대 (Temporal Dead Zone ; TDZ)라 부른다


https://velog.io/@zlfmaodtod77/%EC%8A%A4%EC%BD%94%ED%94%84Scope
(스코프에 대해)

profile
올라가자

0개의 댓글