[JavaScript] 호이스팅 (Hoisting)

예리에르·2021년 5월 28일
2

JavaScript

목록 보기
4/7
post-thumbnail

Hoisting 이란?

  • 함수 안에 있는 선언(var,let,const,function 등)들을 모두 끌어올려서 해당 함수 유효 범위의 최상단에 선언하는 것
  • 전역범위인지 함수 범위인지에 따라서 다르게 동작
  1. 전역 범위 (global scope)
    • 스크립트 단위에서 최상단으로 끌어 올려진다.
  2. 함수 범위 (function scope)
    • 해당 함수의 최상단으로 끌어 올려진다.

호이스팅의 대상

  • var변수선언함수 선언문에서만 호이스팅이 일어난다.
    • 선언만 위로 끌어 올려지며 할당은 끌어 올려지지 않는다.
    • let/const 변수 선언과 함수표현식에서는 호이스팅이 일어나지 않는다.
  • 아래쪽에서 존재하는 내용 중 필요한 값들을 끌어올리는 것이다.
  • 실제 메모리에서는 변화가 없다.
  • 변수의 경우 ES6 문법인 letconst는 초기화 되지 않은 채로 저장이 되고, varundefined로 저장이 된다.

호이스팅 예시

  1. var 변수 VS const/let 변수
var name; // 선언 [Hoisting O]
console.log(name); // undefined
name = 'Jung'; // 할당
console.log(name); // 'Jung'
console.log(name); // undefined
var name = 'Jung'; //[Hoisting O]
console.log(name); // 'Jung'
console.log(name); // ReferenceError
console.log(age); //undefined
const name = 'hoo00nn'; 

var age = 25;
  • ReferenceError : const는 초기화되지 않은 채로 메모리에 저장이 되기 때문에 초기화 전에 변수를 참조할 수 없다.
  1. 함수 선언문 VS 함수 표현식
foo();
foo2();

function foo() { // 함수선언문
        console.log("hello");
}
var foo2 = function() { // 함수표현식
        console.log("hello2");
}
var foo2; // [Hoisting] 함수표현식의 변수값 "선언"

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

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

foo2 = function() { 
        console.log("hello2");
}

  • foo : 함수 선언문으로 hoisting이 일어나면서 'hello' console이 출력된다.
  • foo2 : var로 변수값으로 선언되고 hoisting 되었다. 변수에 할당된 함수표현식은 끌어 올려지지 않았기 때문에 변수의 스코프 규칙을 그대로 유지하면서 Error가 발생한다. 선언된 foo2는 함수가 아니기 때문에 TypeError가 발생되었다.
  1. 함수선언문에서의 호이스팅
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(); // 함수 호출 
  • 함수선언문은 구현 위치와 상관없이 맨 위로 끌어 올려진다.
  1. 함수표현식에서의 호이스팅
    1) 함수표현식의 선언이 호출보다 위에 있는 경우 - 정상

    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(); // 함수 호출 

    2) 함수표현식의 선언이 호출보다 아래에 있는 경우 - TypeError

    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
    https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html

    3) 함수표현식의 선언이 호출보다 아래에 있는 경우 (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

호이스팅의 우선순위

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

  // 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"
  • 값이 할당되어 있지 않은 변수의 경우, 함수선언문이 변수를 덮어쓴다.

마무리

TIP 호이스팅 사용 시 주의

  • 코드의 가독성과 유지보수를 위해 호이스팅이 일어나지 않도록 한다.
    • 호이스팅을 제대로 모르더라도 함수와 변수를 가급적 코드 상단부에서 선언하면, 호이스팅으로 인한 스코프 꼬임 현상은 방지할 수 있다.
    • let/const를 사용한다.
  • var를 쓰면 혼란스럽고 쓸모없는 코드가 생길 수 있다. 그럼 왜 var와 호이스팅을 이해해야 할까?
    • ES6를 어디에서든 쓸 수 있으려면 아직 시간이 더 필요하므로 ES5로 트랜스컴파일을 해야한다.
    • 따라서 아직은 var가 어떻게 동작하는지 이해하고 있어야 한다.

참고)
https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html
https://velog.io/@hoo00nn/%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting-%EC%9D%B4%EB%9E%80

profile
비전공 프론트엔드 개발자의 개발일기😈 ✍️

2개의 댓글

comment-user-thumbnail
2021년 5월 28일

호이스팅은 정말 싫어~

1개의 답글