호이스팅이란

찌끅·2024년 6월 21일

호이스팅이란 무엇인가

함수 안에 있는 선언들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것을 말한다.

  • 자바스크립트 함수는 실행되기 전에 함수 안에 필요한 변수값들을 모두 모아서 유효 범위의 최상단에 선언한다.
    • 자바스크립트 Parser가 함수 실행 전 해당 함수를 한 번 훑는다.
    • 함수 안에 존재하는 변수/함수 선언에 대한 정보를 기억하고 있다가 실횅시킨다.
    • 유효 범위: 함수 블록 { } 안에서 유효
  • 즉, 함수 내에서 아래쪽에 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.
    • 실제로 코드가 끌어올려지는 것은 아니며, 자바스크립트 Parser 내부적으로 끌어올려서 처리하는 것이다.
    • 실제 메모리에서는 변화가 없다.

호이스팅 대상

  • var 변수 선언과 함수선언문에서만 호이스팅이 일어난다.
    • var 변수/함수의 선언만 위로 끌어 올려지며, 할당은 끌어 올려지지 않는다.
    • let/const 변수 선언과 함수 표현식에서는 호이스팅이 발생하지 않는다.
	var myname; // [Hoisting] "선언"
	console.log("hello"); 
	myname = "SEO"; // "할당"
	let myname2 = "won"; // [Hoisting] 발생 X

	var foo2; // [Hoisting] 함수표현식의 변수값 "선언"

    function foo() { // [Hoisting] 함수선언문
            console.log("hello");
    }

    foo();
    foo2(); // ERROR!! 

    foo2 = function() { 
            console.log("hello2");
    }
  • 호이스팅은 함수선언문과 함수표현식에서 서로 다르게 동작하기 때문에 주의해야 한다.
    • 변수에 할당된 함수표현식은 끌어 올려지지 않기 때문에 이때는 변수의 스코프 규칙을 그대로 따른다.

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

함수선언문에서의 호이스팅

  • 함수선언문은 코드를 구현한 위치와 관계없이 자바스크립트의 특징인 호이스팅에 따라 브라우저가 자바스크립트를 해석할 때 맨 위로 끌어 올려진다.
/* 정상 출력 */
function printName(firstname) { // 함수선언문 
    var result = inner(); // "선언 및 할당"
    console.log(typeof inner); // > "function"
    console.log("name is " + result); // > "name is inner value"

    function inner() { // 함수선언문 
        return "inner value";
    }
}

printName(); // 함수 호출 
/* 정상 출력 */
function printName(firstname) { 
    var result; // [Hoisting] var 변수 "선언"

    function inner() { // [Hoisting] 함수선언문
        return "inner value";
    }

    result = inner(); // "할당"
    console.log(typeof inner); // > "function"
    console.log("name is " + result); // > "name is inner value"
}

printName(); 
  • 즉, 해당 예제에서는 함수선언문이 아래에 있어도 printName 함수 내에서 inner를 function으로 인식하기 때문에 오류가 발생하지 않는다.

함수표현식에서의 호이스팅

  • 함수표현식은 함수선언문과 달리 선언과 호출 순서에 따라서 정상적으로 함수가 실행되지 않을 수 있다.
    • 함수표현식에서는 선언과 할당의 분리가 발생한다.
  1. 함수표현식의 선언이 호출보다 위에 있는 경우 - 정상 출력
function printName(firstname) { // 함수선언문
     var inner = function() { // 함수표현식 
         return "inner value";
     }
        
     var result = inner(); // 함수 "호출"
     console.log("name is " + result);
 }

 printName(); // > "name is inner value"
 function printName(firstname) { 
     var inner; // [Hoisting] 함수표현식의 변수값 "선언"
     var result; // [Hoisting] var 변수값 "선언"

     inner = function() { // 함수표현식 "할당"
         return "inner value";
     }
        
     result = inner(); // 함수 "호출"
     console.log("name is " + result);
 }

 printName(); // > "name is inner value"
  1. 함수표현식의 선언이 호출보다 아래에 있는 경우 (var 변수에 할당) - TypeError
function printName(firstname) { // 함수선언문
     console.log(inner); // > "undefined": 선언은 되어 있지만 값이 할당되어있지 않은 경우
     var result = inner(); // ERROR!!
     console.log("name is " + result);

     var inner = function() { // 함수표현식 
         return "inner value";
     }
 }
 printName(); // > TypeError: inner is not a function
 /* 오류 */
 function printName(firstname) { 
     var inner; // [Hoisting] 함수표현식의 변수값 "선언"

     console.log(inner); // > "undefined"
     var result = inner(); // ERROR!!
     console.log("name is " + result);

     inner = function() { 
         return "inner value";
     }
 }
 printName(); // > TypeError: inner is not a function
  1. 함수표현식의 선언이 호출보다 아래에 있는 경우 (const/let 변수에 할당) - ReferenceError
 /* 오류 */
 function printName(firstname) { // 함수선언문
     console.log(inner); // ERROR!!
     let result = inner();  
     console.log("name is " + result);

     let inner = function() { // 함수표현식 
         return "inner value";
     }
 }
 printName(); // > ReferenceError: inner is not defined
  • let/const의 경우, 호이스팅이 일어나지 않기 때문에 위의 예시 그대로 이해하면 된다.
  • console.log(inner);에서 inner에 대한 선언이 되어있지 않기 때문에 이때 "inner is not defined" 오류가 발생한다.

호이스팅 우선순위

같은 이름의 var 변수 선언과 함수 선언에서의 호이스팅

  • 변수 선언이 함수 선언보다 위로 끌어 올려진다.
var myName = "hi";

  function myName() {
      console.log("yuddomack");
  }
  function yourName() {
      console.log("everyone");
  }

  var yourName = "bye";

  console.log(typeof myName);
  console.log(typeof yourName);
 // 1. [Hoisting] 변수값 선언 
  var myName; 
  var yourName; 

  // 2. [Hoisting] 함수선언문
  function myName() {
      console.log("yuddomack");
  }
  function yourName() {
      console.log("everyone");
  }

  // 3. 변수값 할당
  myName = "hi";
  yourName = "bye";

  console.log(typeof myName); // > "string"
  console.log(typeof yourName); // > "string"
  • 값이 할당되어 있지 않은 변수와값이 할당되어 있는 변수에서의 호이스팅
var myName = "Heee"; // 값 할당 
  var yourName; // 값 할당 X

  function myName() { // 같은 이름의 함수 선언
      console.log("myName Function");
  }
  function yourName() { // 같은 이름의 함수 선언
      console.log("yourName Function");
  }

  console.log(typeof myName); // > "string"
  console.log(typeof yourName); // > "function"
  • 값이 할당되어 있지 않은 변수의 경우, 함수선언문이 변수를 덮어쓴다.
  • 값이 할당되어 있는 변수의 경우, 변수가 함수선언문을 덮어쓴다.

0개의 댓글