웹/JavaScript

JavaScript 실행 컨텍스트(execution context)와 호이스팅(hoisting)

클라우드아실 2021. 1. 10. 22:31

JavaScript 실행 컨텍스트(execution context)와 호이스팅(hoisting)

 : 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체 입니다. 이를 위해서 스택(stack)과 큐(queue)라는 데이터 구조에 대해 알고 있어야 합니다. 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행합니다.

STACK 구조
IN (a, b, c, d) -> OUT (d, c, b, a)

QUEUE 구조
IN (a, b, c, d) -> OUT (a, b, c, d)
  • STACK 구조는 우물 같은 데이터 구조입니다. 저장한 데이터가 차곡차곡 쌓이면 꺼낼 때는 반대순서가 됩니다. 
  • QUEUE 구조는 파이프 같은 데이터 구조입니다. 저장한 데이터가 들어가는 순서대로 꺼낼 때도 그대로 빠져나옵니다.

 

호이스팅(hoisting)

 : 호이스팅이란 선언 부분이 최상단으로 끌어올려지는 것을 의미합니다. 함수를 어디서 선언하든지 실행할 수 있도록 개발한 것이라 추정되나 오히려 혼란이 발생했습니다. 실제로 끌어올려지는 것은 아니고 그와 같은 원리라 보면 되겠습니다. 실행 컨텍스트의 선언된 변수나 함수(식별자)는 최상단으로 끌어올리고 할당은 원래 자리에서 할당하게 됩니다.

function a() {
  console.log(b)
  
  var b = 'bbb';
  
  console.log(b);
  
  function b () { }
  
  console.log(b);
}

a();
  • 원래 코드. error, 'bbb', b함수가 나올 것 같습니다.

 

function a() {
  var b
  function b () { }
  
console.log(b)
  
  b = 'bbb';
  
  console.log(b);
  
  console.log(b);
}

a();
  • 실행 후 호이스팅 적용된 진행순서. 함수와 변수가 최상위로 이동. 실제로는 b함수, 'bbb', 'bbb' 순으로 반환됩니다.

 

 : 함수 선언문은 함수 안의 내용까지 전체 호이스팅하지만 함수 표현식은 변수 선언부만 호이스팅하고 값에 해당하는 할당부분은 마찬가지로 원래 위치에 유지됩니다. 함수 표현식과 선언식의 차이가 이부분입니다.

function a() {
  console.log(b)
  
  var b = 'bbb';
  
  console.log(b);
  
  var b = function () { } // 이부분만 함수 표현식으로 수정
  
  console.log(b);
}

a();
  • 원래 코드

 

function a() {
  var b 
  console.log(b)
  
  b = 'bbb';
  
  console.log(b);
  
  b = function () { } // 이부분만 함수 표현식으로 수정
  
  console.log(b);
}

a();
  • 실행 후 호이스팅 적용된 진행순서.  undefined, 'bbb', b함수 순으로 반환됩니다.

다시 보는 스코프체인(Scope Chain)

 : 함수가 중첩되어 있을 때 함수 내부에서 외부로 검색해 나가는 것을 스코프체인이라고 합니다. 이 때도 호이스팅이 적용됩니다.

var a = 1;
var outer = function () {
  var inner = function () {
    console.log(a);
    var a = 3;
    };
  inner();
  console.log(a);
  };
outer();
console.log(a);
  • 원래코드

 

var a = 1;
var outer
  outer = function ()
  outer();  
  {var inner
  inner = function () {
    var a
    console.log(a);
    a = 3;
    };
    inner();
    console.log(a);
  };
console.log(a);
  • 실행 후 호이스팅 적용된 진행순서
  • 첫번째로 변수 a에 1이 할당됩니다. outer가 선언되고 함수가 할당 됩니다.
  • 그리고 하단의 함수 outer() 가 호출됩니다.
  • outer 함수 안에 변수 inner가 선언 및 함수가 할당됩니다.
  • 그리고 하단의 함수 inner() 가 호출됩니다.
  • 선언된 변수 a가 inner함수 내 최상단으로 호이스팅 됩니다.
  • 할당전 console.log로 undefined가 출력됩니다.
  • 이후 a=3이 할당되지만 함수스코프로 inner함수 밖으로 벗어나지 못합니다.
  • 그 다음 console.log(a)는 해당 outer 함수 내에 a를 찾을 수 없으므로 외부 전역변수 a의 1을 출력합니다.
  • 마지막으로 console.log(a)도 동일하게 전역변수 a에 할당된 1을 출력합니다.

 

정리

  • 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체
  • 식별자만 따로 분리해서 처리. 호이스팅이 발생한다.
  • 호이스팅이란 실행 컨텍스트의 선언된 변수나 함수는 최상단으로 끌어올리고 할당은 원래 자리에서 하는 것
  • 코드의 안전성을 위해 가급적 전역변수 사용을 최소화 할 것
  • let, const 사용 등으로 스코프를 명확하게 할 것

 

참고

코어 자바스크립트 - 정재남 저 위키북스

제로초 - 실행 컨텍스트

PoiemaWeb - 실행 컨텍스트와 자바스크립트의 동작 원리

MDN - Hoisting