[JS] 실행 컨텍스트 - environmentRecord와 호이스팅

이승혜·2021년 9월 3일
0

JS/JQUERY

목록 보기
5/10
post-thumbnail

이 글은 📕코어 자바스크립트 책을 바탕으로 정리한 글입니다.

💡 envirionmentRecord와 호이스팅

  • envirionmentRecord : 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장되는 곳
  • 컨텍스트를 구성하는 함수에 지정된 매개변수 식별자, 함수 자체(선언한 함수가 있을 경우), var로 선언된 변수의 식별자 등
  • 컨텍스트 내부 전체를 처음부터 쭉 훑으며 순서대로 수집

📌 전역 실행 컨텍스트는 변수 객체를 생성하는 대신 자바스크립트 구동환경이 별도로 제공하는 객체, 즉 전역 객체(global object)를 활용한다.
전역 객체에는 브라우저의 window, Node.js의 global객체 등이 있다.
이들은 자바스크립트의 내장 객체(native object)가 아닌 호스트 객체(host object)로 분류된다.

alert("Hello")
// 위와 동일하게 동작함
window.alert("Hello")

var a = 5
alert(window.a); // 5 (var로 선언한 변수는 전역 객체 window의 프로퍼티가 됨

let b = 5
alert(window.b) // undefined (let으로 선언한 변수는 전역 객체의 프로퍼티가 되지 않음!)

변수 정보를 수집하는 과정을 모두 마쳤기 때문에, 코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있게 되었다.
이 말은 즉 '자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다'라고 봐도 무방하다.
여기서 등장하는 개념이 호이스팅(hoisting)이다.

📌 호이스팅이란 '끌어올리다'라는 의미의 hoist에 ing를 붙여 만든 동명사로, 변수 정보를 수집하는 과정을 더욱 이해하기 쉬운 방법으로 대체한 가상의 개념이다.
실제로 자바스크립트 엔진이 끌어올리는 것은 아니지만 편의상 끌어올린 것으로 간주하자는 것!

호이스팅 규칙

environmentRecord에는 매개변수의 이름, 함수 선언, 변수명 등이 담긴다고 했다.
예제를 통해 호이스팅에 대해 알아보자

호이스팅 규칙 예제 1 (원본 코드)

function a(x) { // 수집 대상 1(매개 변수)
  console.log(x); // (1)
  var x; // 수집 대상 2(변수 선언)
  console.log(x); // (2)
  var x = 2 // 수집 대상 3(변수 선언)
  console.log(x); // (3)
}
a(1)

우선 호이스팅이 되지 않았을 때 (1),(2),(3)에서 어떤 값들이 출력될지 예상해보자
(1)에는 함수 호출 시 전달 된 1이 출력되고,
(2)에는 선언된 변수 x에 할당된 값이 없으므로 undefined가 출력되고,
(3)에는 2가 출력될 것이라 예상된다
실제로는 어떤 결과가 나오는지 알아보자

밑에서 설명하는 예제들은 자바스크립트 엔진의 구동 방식을 좀 더 쉽게 이해해보고자 변경한 것일 뿐 실제로 이런 변환을 거치지 않으니 유의할 것!

호이스팅 규칙 예제 2 (매개 변수를 변수 선언/할당과 같다고 간주해서 변환한 상태)

function a(){
  var x = 1; // 수집 대상 1(매개변수 선언)
  console.log(x); // (1)
  var x; // 수집 대상 2(변수 선언)
  console.log(x); // (2)
  var x = 2; // 수집 대상 3(변수 선언)
  console.log(x); // (3)
}
a();

이 상태에서 변수 정보를 수집하는 과정, 즉 호이스팅을 처리해보자
envirionmentRecord는 현재 실행될 컨텍스트의 대상 코드 내에 어떤 식별자들이 있는지에만 관심이 있고, 어떤 값이 할당된 것인지는 관심이 없다.
따라서 변수를 호이스팅할 때 변수명만 끌어울리고, 할당 과정은 원래 자리에 그대로 남겨둔다(매개변수의 경우도 마찬가지).

호이스팅 규칙 예제 3 (호이스팅을 마친 상태)

function a(){
  var x; // 수집 대상 1의 변수 선언 부분
  var x; // 수집 대상 2의 변수 선언 부분
  var x; // 수집 대상 3의 변수 선언 부분
  
  x= 1; // 수집 대상 1의 할당 부분
  console.log(x); // (1)
  console.log(x); // (2)
  x = 2; // 수집 대상 3의 할당 부분
  console.log(x); // (3)
}
a(1);

따라서 (1),(2) 모두 1이 출력되고 (3)에서는 2가 출력되는 것을 볼 수 있다.
(2)에서 undefined가 아닌 1이 출력된다는 건 호이스팅 개념을 정확히 이해해야 예측할 수 있는 결과인 것이다.

호이스팅 규칙 응용 예제

function a(){
  console.log(b); // (1)
  var b = 'bbb';
  console.log(b); // (2)
  function b() {...}
  console.log(b); // (3)
 }
a();

위와 같은 코드가 있다.
호이스팅 개념을 배우지 않았다면
(1)에서는 undefined
(2)에서는 'bbb'
(3)에서는 함수 b가 출력될 것이라고 예상하겠지만,
우리는 호이스팅 개념을 배웠다

function a(){
  var b;
  var b = function b () {...} // 바뀐 부분 
  
  console.log(b); // (1)
  b = 'bbb';
  console.log(b); // (2)
  console.log(b); // (3)
 }
  a();

호이스팅 결과,
(1)에서는 b 함수,
(2),(3)에서는 'bbb'가 출력되는 것을 확인할 수 있다.

다음 페이지에서는 호이스팅을 배울 때 알아두면 좋을 함수 선언식과 함수 표현식에 대해 다뤄보자

profile
더 높이

0개의 댓글