면접-JavaScript #01 | 함수 선언식과 함수 표현식

📚 개념 요약

함수 선언식은

function foo() {
  구현 로직
}

함수 표현식은

var foo = function () {
  구현 로직
};
//또는 (아래 권장)
const short = function longUniqueMoreDescriptiveLexicalFoo() {
  구현 로직
};

📌 호이스팅에서의 차이

함수 선언식은 함수 호이스팅이 일어나지만, 함수 표현식은 변수 호이스팅이 일어난다.

// 실행 전
logMessage();
sumNumbers();

function logMessage() {
  return 'worked';
}

var sumNumbers = function () {
  return 10 + 20;
};

위와 같은 코드가 JS 엔진이 아래와 같이 코드를 해석한다.

// 실행 시
function logMessage() {
  return 'worked';
}

var sumNumbers;

logMessage(); // 'worked'
sumNumbers(); // Uncaught TypeError: sumNumbers is not a function

sumNumbers = function () {
  return 10 + 20;
};

아래의 예시도 살펴보자.

/* 정상 동작 */
var sumNumbers = function (num1, num2) {
  return num1 + num2;
};

printSumNumbers(sumNumbers, 10, 20);

function printSumNumbers(fn, num1, num2) {
  console.log(fn(num1, num2));
}

/* 오류 */
printSumNumbers(sumNumbers, 10, 20);

var sumNumbers = function (num1, num2) {
  return num1 + num2;
};

function printSumNumbers(fn, num1, num2) {
  console.log(fn(num1, num2));
} //sumNumbers가 선언식이었다면 정상동작

📌 선호하는 방식은 함수 표현식

함수 표현식이 “호이스팅에 영향을 받지 않는다”는 특징 이외에도 클로저로 사용되는 특징을 가진다.

/* 클로저 없이 */
var tabs = document.querySelectorAll('.tab');
var i;

for (i = 0; i < tabs.length; i += 1) {
    tabs[i].onclick = function (event) {
      console.log(i); // 어느 탭을 클릭해도 항상 tabs.length가 출력
    };
}

/* 클로저로 사용 */
function tabsHandler(index) {
    return function tabClickEvent(event) {
        console.log(index);
    };
}

var tabs = document.querySelectorAll('.tab');
var i;

for (i = 0; i < tabs.length; i += 1) {
    tabs[i].onclick = tabsHandler(i);
}

결국 이러한 차이점을 인지한 상태에서 일관된 코딩 컨벤션으로 코드를 작성하는 게 중요하다. AirBnb 의 JS Style 가이드 에서는 함수 선언식보다는 함수 표현식을 지향한다.

💡 질문

❓ 함수 선언식과 함수 표현식의 차이

함수 선언식은 다른 언어에서의 함수 선언과 마찬가지로 function키워드의 뒤에 함수명과 매개변수를 작성해서 함수를 정의하는 방식입니다. JS엔진이 런타임 이전에 코드의 맨 앞으로 끌어 올리는 호이스팅 특징에 의해서 함수 호출보다 더 뒤에 함수를 정의했더라도 정상적으로 동작하게 됩니다.

함수 표현식은 Javascript의 유연한 특징을 활용해서 변수에 Function객체를 저장하는 방식입니다. 호이스팅의 영향을 받더라도 함수 호이스팅이 아닌 변수 호이스팅이 일어나기 때문에 함수를 작성한 코드보다 함수 호출을 더 앞에 하게되면 해당 변수에는 Function객체가 아닌 undefined가 초기화된 시점에서 동작하기 때문에 타입에러가 발생하게 됩니다.

+) 호이스팅이라는 특징 말고도 함수표현식은 클로저나 콜백함수에서 유용하게 쓰이고 있습니다. 일관된 코딩 컨벤션을 갖고 코드를 작성하는 게 중요하다고 생각을 하는데 저는 주로 함수 표현식의 방법을 사용하고 있습니다.