[javascript] hoisting (호이스팅)

chaeyeon·2023년 1월 18일
0
post-thumbnail
post-custom-banner

호이스팅(hoisting)이란 '끌어올리다'라는 의미의 hoist + ing를 붙여 만들어졌으며 의미 그대로 끌어올리는 행위로 작동한다. 주로 var로 선언된 변수의 선언문을 코드의 최상단으로 끌어올인다. (변수 정보를 수집하는 과정을 이해하기 쉬운 방법으로 대체한 가상의 개념으로, 자바스크립트 엔진이 실제로 끌어올리지는 않지만 편의상 끌어올린 것으로 간주된다.)

호이스팅

실행컨텍스트에 담기는 LexicalEnvironment의 내부는 environmenRecord와 outer-EnvironmenReference로 구성되는데 environmenRecord는 호이스팅과 관련이 있다.

  • environmenRecord: 현재 컨텍스트와 관련된 코드의 식별자 정보를 순서대로 저장
    (식별자: 컨텍스트를 구성하는 함수에 지정된 매개변수, 함수자체, var로 선언된 변수의 식별자 등)

식별자 정보를 수집하는 과정을 마쳐도 코드가 실행되기 전이기 때문에 실행컨텍스트가 관여한 코드들은 실행되기 전의 상태이다. (실행전이지만 수집과정을 거쳤기 때문에 해당 환경의 변수명을 모두 알고 있다.)

  1. 실행컨텍스트의 LexicalEnvironment의 내부 environmenRecord가 처음부터 끝까지 순서대로 식별자를 수집한다.
  2. 코드가 실행되기 전이지만 1의 수집과정을 거쳤기 때문에 자바스크립트 엔진은 해당 환경의 변수명을 모두 알고 있다.
    (= 식별자들을 최상단으로 끌어올려놓은 다음 코드를 실행한다고 간주)


호이스팅 규칙

*변수명함수 전체의 정보를 위로 끌어올리고 할당과정은 원래 자리에 남겨둔다.

function a() {
    console.log(b); // ƒ b() { }
    var b = 111; // ← 수집대상 1
    console.log(b); // 111
    function b() { // ← 수집대상 2
        console.log(b) // 111
    }
}
a();

a함수를 실행하는 순간 a 함수의 실행 컨텍스트가 생성된다. (변수명과 함수가 위로 끌어올려진다.)

위의 코드에서는 수집대상 1과 2를 순서대로 끌어올리고 다음과 같은 형태로 동작한다.

// 호이스팅 완료 (실제 변환과정이 아닌 쉽게 이해하기 위한 예시 코드)
function a() {
    var b;
    function b() {};

    console.log(b);   //  ƒ b() { }
    b = 111;
    console.log(b);   //  111
    console.log(b);   //  111 
}
a();
  1. 수집대상 1의 변수명 b와 함수 b를 위로 끌어올려 선언한다.
  2. 다시 변수 b를 선언하고 함수 b를 선언된 변수 b에 할당한다.
  3. 첫번째 console은 변수 b에 할당된 함수 b를 출력한다. (*나중에 선언된 111이 아닌 함수 b가 처음 출력된다)
  4. b에 숫자 111을 할당한다.
  5. 두번째, 세번째 console은 마지막으로 할당된 숫자 111을 출력한다.


함수선언문과 함수 표현식 호이스팅

함수 선언문(function declaration)은 function 정의부만 존재하고 별도의 할당 명령이 없는 것을 의미하고, 함수 표현식(function expression)은 정의한 function을 별도의 변수에 할당하는 것을 말한다.

console.log(sum(1, 2));   //  3
console.log(multiply(3, 4));   //  Uncaught TypeError: multiply is not a function
// 1. 함수 선언문
function sum(a, b) {
    return a + b;
}
// 2. 함수 표현식
var multiply = function (a, b) {
    return a * b;
}

함수가 선언된 후에야 호출 할 수 있기 때문에 예시에서 함수 표현식으로 정의된 multiply(3, 4)를 호출하면 'Uncaught TypeError' 에러가 뜬다. 호이스팅 된 상황을 아래의 코드로 재현해보면,

// 호이스팅 완료

/* 함수 선언문 전체가 끌어올려진다.*/
function sum(a, b) {
    return a + b;
}
/* 함수 표현식의 변수만 끌어올려진다. */
var multiply;
console.log(sum(1, 2));   //  3

/* 변수 multiply만 선언되었기 때문에 TypeError가 발생한다. */
console.log(multiply(3, 4));   //  Uncaught TypeError: multiply is not a function

multiply = function (a, b) {
    return a * b;
}

*다수의 개발자들이 협업할 때, 각각의 개발자가 함수 선언문을 이용해서 동일한 함수명으로 개발하였다면 호이스팅으로 인한 문제가 발생한다. (코드가 덮어씌워지는 문제가 발생한다.) 따라서 여러명이 협업할 때 함수는 함수 표현식을 이용하여 개발하도록 해야한다.

참고 : 코어 자바스크립트(정재남)

profile
4년차 퍼블리셔에서 프론트엔드 개발자로 이직 성공한 신입 개발자 입니다-*
post-custom-banner

0개의 댓글