[JS] 실행컨텍스트에서의 호이스팅

colki·2021년 3월 31일
0

호이스팅에 대해서 일전에 공부를 했었지만, 부족함을 느끼고 있었다.
this공부를 마치고 다시 호이스팅 관련 예제를 풀어보니 오답만 말하고 있는 나 자신을 발견..😲
코어자바스크립트 예제를 보면서 다시 되새김질을 해보려고 한다.

Hoisting

호이스팅을 다루기 전에 먼저 environmentRecord에 대해서 얘기하려고 한다.
environmentRecord 에는 현재 컨텍스트의 코드와 식별자 정보가 저장된다.
자바스크립트 엔진은 먼저 해당 컨텍스트를 처음부터 순서대로 읽어내려가며 정보를 수집한다.

그래서 코드가 실행되기 전이지만 자바스크립트 엔진은 이미 변수에 대해서 알고 있는 것이다.
이렇게 먼저 자바스크립트 엔진이 정보를 수집하는 과정을 이해하기 쉽게 표현한 것이 호이스팅인데, 호이스팅이란
자바스크립트 엔진이 스코프내에서 선언된 const, var, let, 함수선언문 등을 최상단으로 끌어올려서 먼저 해석하는 것을 가리킨다.
실제로는 그렇게 끌어올리지 않지만 이해하기 쉽게 편의상 끌어올린다고 말하는 것이다.

함수 안에서 일어나는 호이스팅에 대해서 살펴볼건데
먼저 매개변수가 있을 때와 없을 때에 따라 차이가 생긴다.

① 매개변수가 있을 때 호이스팅

아래 예제에서 각 콘솔에 출력되는 값은 무엇일까?

function foo(a) {
  console.log(a); // ---?
  var a;
  console.log(a); // ---?
  var a = 2;
  console.log(a); // ---?
}

foo(1);

매개변수에 값이 담기는 방식을 제외하면
코드 내부상단에서 변수를 선언하고 값을 할당하는 것과 차이가 없다.

즉 자바스크립트엔진은 위 코드나 아래 코드와 완전히 동일하게 해석한다.
정답은 아래에서 확인해보시라!


② 매개변수가 없을 때 호이스팅

function foo2() {
  var a =1
  console.log(a); // ---?
  var a;
  console.log(a); // ---?
  var a = 2;
  console.log(a); // ---?
}

foo2();

첫 번째 예제에서 매개변수에 1이라는 값을 받았을 때도,
자바스크립트는 위 코드처럼 해석한다.

foo 스코프내부 최상단에서 var a = 1;로 변수에 값이 할당된 것처럼 말이다.

  • 호이스팅 해석
function foo2() {
  var a;
  var a;
  var a;
  a =1
  console.log(a); // 1
  console.log(a); // 1
  a = 2;
  console.log(a); // 2
}

foo2();

1, undefined, 2 가 나올거라 예상했던 것과 달리 콘솔창에는 1, 1, 2 가 출력된다!

호이스팅과정에서는 값이 할당되는 부분은 그자리에 있고, 변수명만 최상단으로 먼저 끌어올려진다.
즉 console.log(a)와 a=1, a=2는 자신들의 자리에 가만히 있고
var a만 나란히 3개가 순서대로 위치하게 된다.

변수를 수집하는 과정에서는, 변수에 할당된 값에 대해서는 궁금해하지 않은 채
무슨 무슨 식별자들이 있는지만 확인한다.

③ 함수선언문의 호이스팅

앞에서 살펴본 식별자와 달리 함수선언문은 함수 전체가 통째로 끌어올려진다.

function bar() {
  console.log(b); // ---?
  var b = 'colki';
  console.log(b); // ---?
  function b() {
    console.log('hello');
  }
  console.log(b); // ---?
}

bar();

함수선언문이 포함되어 있는 함수스코프 내에서의 호이스팅은 어떻게 될까?

  • 호이스팅 해석
function bar() {
  var b;
  function b() {
    console.log('hello');
  }
  
  console.log(b); // ƒ b() { console.log('hello'); }
  b = 'colki';
  console.log(b); // colki
  console.log(b); // colki
}

bar();

undefined, colki, 함수 b가 출력될 거라고 자신있게 생각했었지만 역시 정답이 아니었다.
해석을 살펴보면 var b 그리고 바로 다음에 함수선언문이 호이스팅 되었다.

함수는 함수잖아? 뭐지? 여기서부터 머리가 잘 안돌아가는 현상이 생길 수 있다.
함수선언문 이라는건 변수선언문과 의미가 같다. 변수의 형태가 아닌 함수의 형태로 값을 할당하는 것 뿐이다.

이해하기 쉽게 직역?한다면 아래와 같다.

function bar() {
  var b;
  var b = function b() {
    console.log('hello');
  }
  
  console.log(b); //
  b = 'colki';
  console.log(b); // 
  console.log(b); // 
}

bar();

호이스팅된 함수를 다시보니 함수표현식과 닮아 있다. '0'

b라는 이름을 가진 함수는 변수 b와 결이 같기 때문에 var b 자리에 함수 b가 눌러앉은 것이다.
그래서 함수가 그 자리에 앉았으므로 var b는 함수 b로 덮어씌워진다.
즉 변수 b에 새롭게 함수 b로 할당되는 것이다.

그러므로 처음으로 출력되는 값은 ƒ b() { console.log('hello'); }가 된다.

b = colki 에서는 b의 값에 colki를 새로 할당하라고 하니 이제부터 b는 colki를 가리키게 되므로
나머지 두 개다 colki가 출력된다.

profile
매일 성장하는 프론트엔드 개발자

0개의 댓글