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

이현지·2021년 3월 14일
4

javascript 코드를 보면 다음과 같은 경우를 보았을 것이다.

function getName() {
    console.log('name');
}

var name = function() {
   console.log('name');
};
  • javascript 에서 함수를 변수에 담을 수 있다.
    이렇게 사용하는 것을 함수 표현식 이라고 한다.
    그리고 function getName() 과 같이 함수를 선언하는 것을 함수 선언문이라고 한다.

그렇다면 함수 표현식과 함수 선언문 둘다 함수인데 어떻게 다르며, 어떻게 사용되는지 알아보자.
우선 둘의 차이는 호이스팅을 빼놓고 설명할 수 없다.

호이스팅

  • 호이스팅(Hoisting)의 사전적 의미는 끌어 올리다 라는 뜻을 가지고 있다.
    여기서도 같은 의미로 쓰인다. 함수 안에 있는 변수나 함수 맨위로 끌어올린다는 것이다.

  • 실제로 코드가 끌어올려지는 것은 아니며, 자바스크립트 Parser가 내부적으로 끌어올려서 처리한다.

호이스팅 대상

  • var함수 선언문 이 호이스팅 대상이다.
    let 또는 const 그리고 함수 표현식은 해당되지 않는다.

호이스팅 규칙

부등호가 큰 쪽이 먼저 인식된다

  • 변수 선언 > 함수 선언
  • 할당되어있는 변수 > 할당되지 않은 변수

함수표현식의 호이스팅

  • 다음 예제들의 결과를 생각해보자.
count();

var count = function() {
    console.log('count는 1이다.');
}
var count = function() {
    console.log('count는 1이다.');
}

count();
count();

let count = function() {
    console.log('count는 1이다.');
}

  • 첫번째 결과는 TypeError 이다. error : count is not function

count() 호출 후, var count를 선언하며 함수를 담았다.
var 는 호이스팅의 영향을 받으므로 위로 끌어올려진다.
그러므로 아래와 같이 var count; 가 가장 먼저 실행된다. 변수에 아무 값도 담지 않았으므로 undefined 상태이다.
그 후로 count()가 호출되면 위에 선언한 count가 호출되므로 변수를 호출하는 격이된다.
그러므로 not function 이라는 에러 메시지가 나타난다.

var count;    // undefined

count();      // count는 함수가 아닌데 왜 함수를 호출하니?

var count = function() {
    console.log('count는 1이다.');
}
  • 두번째 결과는 정상적으로 console.log가 동작한다.

var count가 호이스팅으로 인해 위로 끌어올려지지만, count() 호출 전 count에 함수를 담으므로
count() 를 호출하였을 때 정상 작동한다.

var count;    //undefined

var count = function() {
    console.log('count는 1이다.');
}

count();
  • 세번째 결과는 ReferenceError 이다.

세번째 예시는 첫번째 예시에서 varlet으로 바꾼 것이다.
세번째도 역시 에러를 발생하지만, 첫번째와 다른 Referecne Error가 발생한다.
let 은 호이스팅의 영향을 받지 않기 때문에, 예시 작성한 코드 순서대로 실행된다.
그러므로 count()라는 함수가 정의되지 않았는데 호출하였기 떄문이다.

count();

let count = function() {
    console.log('count는 1이다.');
}

함수선언문의 호이스팅

count();

function count() {
    console.log('count는 2이다.');
}
function count() {
    console.log('count는 2이다.');
}

count();

  • 첫번째, 두번째 모두 정상 작동한다.
    호출이 함수선언문의 위에 있든 아래쪽에 있든 함수 선언문은 호이스팅 영향으로 끌어올려지기 때문이다.

결론

함수선언문을 사용하는게 좋을까? 함수표현식을 사용하는게 좋을까?
찾아보니 어떤 사람은 함수 선언문을 권장하고, 또 어떤사람은 함수 표현식을 권장한다.
또한 두 개의 차이는 없고 한가지만 사용하는 것이 좋다는 사람도 있어 뭐라 결론을 내리지 못하겠다.
개인적으로 const와 let을 사용하며, 코드 순대로 동작하게 작성하는 것이 호이스팅의 영향을 최소화 할 수 있고, 호이스팅의 영향을 최소화하는 것이 가독성이나 유지보수측면에서도 좋지 않을까 생각한다.

Reference

https://gmlwjd9405.github.io/2019/04/22/javascript-hoisting.html
https://yuddomack.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85Hoisting
https://ko.javascript.info/function-expressions

profile
Backend Developer👩‍💻

3개의 댓글

comment-user-thumbnail
2022년 12월 20일

많은 도움이 되었습니다!

답글 달기
comment-user-thumbnail
2023년 2월 25일

개념을 이해하는데 많이 도움이 되었습니다. 감사합니다.

답글 달기
comment-user-thumbnail
2023년 5월 13일

세번째 결과는 엄밀하게 따지면 let 호이스팅은 발생해서 선언은 되었지만 undefined로 초기화 되지 못해서 Reference error를 띄운게 맞지 않나요?

답글 달기