Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript 즉시 실행 익명 함수와 호이스팅: 출력 결과는 무엇일까?

문제 상황

다음과 같은 코드 조각이 있다고 가정해 보겠습니다. 이 코드의 실행 결과를 예측하고, 그 이유를 설명하는 것이 과제입니다.

var name = 'Zakir';
(() => {
    name = 'Rahul';
    return;
    console.log(name);
    function name(){
       let lastName = 'Singh';
    }
})();
console.log(name);

직관적인 접근: 한 줄씩 분석하기

먼저 가장 단순한 방식으로 코드를 한 줄씩 살펴보겠습니다.

  • 1행 → 변수 name에 'Zakir'가 저장됩니다.
  • 3행 → 즉시 실행 익명 함수(IIFE) 내부로 진입합니다.
  • 4행 → 변수 name이 'Rahul'로 재할당됩니다.
  • 5행return 문을 만나 함수를 빠져나갑니다.
  • 15행 → 현재 값이 'Rahul'인 name 변수를 화면에 출력합니다.

따라서 최종 출력은 다음과 같다고 생각하기 쉽습니다.

Rahul

하지만 안타깝게도 이 답은 틀렸습니다. 그렇다면 어디서 잘못된 걸까요? 이번에는 변수 호이스팅(variable hoisting)함수 호이스팅(function hoisting) 개념을 염두에 두고 코드를 다시 분석해 보겠습니다.

호이스팅을 고려한 올바른 분석

  • 1행 → 변수 name에 'Zakir'가 저장됩니다.
  • 3행 → 즉시 실행 익명 함수 내부로 진입합니다.

함수에 진입하는 순간 함수 호이스팅이 발생합니다. 즉시 실행 함수 맨 아래에 정의된 함수 name()이 해당 함수 스코프의 가장 위로 끌어올려집니다. 이 중간 상태에서 코드는 사실상 다음과 같은 형태가 됩니다.

예제: 호이스팅 적용 후의 코드

let name = 'Zakir';
(() => {
    let name; // 함수 선언이 호이스팅되어 지역 바인딩이 생성됨
    name = 'Rahul';
    return;
    console.log(name);
    name = function(){
       let lastName = 'Singh';
    }
})();
console.log(name);

여기서 중요한 점을 기억해야 합니다. 변수나 함수가 스코프의 최상단으로 호이스팅될 때는 선언(정의)만 끌어올려지고, 초기화는 원래 작성된 위치에서 일어납니다. 따라서 스코프 최상단에서 해당 이름은 존재하지만 값은 undefined입니다.

그 결과, name이 'Rahul'로 재할당될 때 전역 변수가 아니라 함수 스코프 내의 지역 변수 name이 재할당됩니다. 이후 return으로 즉시 실행 함수를 빠져나와 전역 변수 name을 콘솔에 출력하면, 전역 변수는 여전히 'Zakir'를 담고 있으므로 출력 결과는 다음과 같습니다.

실행 결과

Zakir

핵심 정리

이 문제의 핵심은 두 가지입니다.

  1. 함수 선언도 호이스팅 대상입니다. 함수 내부 어디에 선언되었든, 함수 선언문은 해당 스코프의 최상단으로 끌어올려져 지역 바인딩을 만듭니다.
  2. 호이스팅은 선언만 끌어올립니다. 초기화는 원래 위치에서 수행되므로, 스코프 상단에서의 값은 undefined입니다.

즉, 겉보기에는 전역 변수를 수정하는 것처럼 보이지만, 실제로는 함수 내부에 별도의 지역 바인딩이 존재했기 때문에 전역 변수는 그대로 유지되어 'Zakir'가 출력되는 것입니다.