Hoisting이 정확히 무엇인지 구글링해보면 "함수나 변수 등이 해당 범위의 맨 위로 올라가는 것 같은 현상"이라는 사람도 있고, 혹은 "맨 위로 올라가는 것 같은 현상의 동작 원리 자체"를 호이스팅이라고 하는 사람도 있다.
이 애매한 상황을 해결하기 위해 MDN을 참고했다.
JavaScript Hoisting 은 인터프리터가 코드를 실행하기 전에 함수, 변수 또는 클래스 의선언 을 해당 범위의 맨 위로 이동하는 것처럼 보이는 프로세스를 나타냅니다.
물론HoistableDeclaration
으로 정의하지만 여기에는function
,function*
,async function
및async function*
선언만 포함됩니다.
[MDN] https://developer.mozilla.org/en-US/docs/Glossary/Hoisting결론
MDN을 참고해보면 ECMA spec.에 정식으로 등록된 것은 아니고 "함수나 변수 등이 맨위 올라가는 것처럼 보이는 현상"을 구어체적으로 표현하는 단어다.(Hoisting 자체가 합의된 용어가 아니기 때문에 여러 의견으로 갈리는 것이 당연한 것 같다.)
함수가 생성되면, 해당 함수에 대한 정보들을 모아놓은Excution Context
가 생성된다. 이 때, 함수 내에 선언된 함수 선언식
과 변수
들이 Excution Context
내에 있는 Lexical Environment
에 저장된다. Lexical Environment
에 미리 저장된 이 정보들을 통해 우리가 선언 코드보다 위에서 함수 선언식
과 변수
들에 접근할 수 있는 것이다.
Lexical Environment
Lexical Environment
는 변수 식별자(variable-identifier)를 매핑하여 갖고있는 데이터 구조다.
<
Lexical Environment와 Excution Context에 대한 정리>
https://velog.io/@tt8784/Excusion-Context-Closure-%EC%9A%94%EC%A0%90%EB%A7%8C
<
함수 선언식 Hoisting>
hellowWorld
라는 함수 선언식은 앞서 말했듯이 Excution Context
의 생성단계에 Excution Context
가 가지고 있는 Lexical Environment
라는 곳에 저장된다.
Lexical Environment
는 다음과 같은 코드를 가지게 된다.
그래서 JavaScript 엔진이 helloWorld()
라는 함수를 만나게 되면, Lexical Environment
에서 해당 함수를 찾아 실행시킬 수 있다.
<함수 표현식 Hoisting
>JavaScript에서는 함수 선언식
만 Hoisting이 된다.(함수 표현식
은 X)
따라서 위와 같은 경우에는 helloWold
가 함수가 아닌 변수로서 저장이 되고, JavaScript엔진은 helloWorld
의 값을 undefined
로 저장하게 된다.
코드는 아래와 같이 바꿔줘야 작동한다.
<var 변수 Hoisting
>위 코드에서 a
의 기대값이 3
이지만 output은 undefined
이다.
JavaScript에서의 hoisting은 선언을 hoisting하는 것이지, 초기화를 얘기하는 것은 아니다.
그렇다면 왜 undefined
일까?
JavaScript엔진이 var
변수 선언을 만나면 이것은 Lexical Environment
에 undefined
로 초기화해서 추가한다.
그리고 a
를 3
으로 초기화 하는 코드를 만나면 Lexical Environment
에서도 a
의 값을 3
으로 업데이트한다.
<let, const 변수 Hoisting
>Example
Output
ReferenceError
가 발생한다. 왜일까?
let, const
도 마찬가지로 Lexical Environment
에 등록된다. 하지만 undefined
로 초기화 되지 않고 uninitialized
상태로 저장된다
그리고 let, const
는 uninitialized
상태에서 runtime
에 값이 동적으로 정해진다.
즉 우리는 엔진이 선언된 코드를 만나 값이 정해지기 전까지 해당 변수에 접근할 수 없다.
이것을 Temperal Dead Zone
이라고 부른다.
[참고한 블로그]
https://blog.bitsrc.io/hoisting-in-modern-javascript-let-const-and-var-b290405adfda