함수 선언식

JavaScript에서 function 키워드를 사용하여 이름이 있는 함수를 선언하는 방식으로, 호이스팅에 의해 선언 전에도 호출할 수 있는 특징을 가집니다.

함수 선언식 vs 함수 표현식

항목함수 선언식 (Declaration)함수 표현식 (Expression)
문법function 이름() {}const 이름 = function() {}
호이스팅전체가 호이스팅됨 (선언 전 호출 가능)변수만 호이스팅 (선언 전 호출 불가)
이름필수선택 (익명 함수 가능)
세미콜론필요 없음필요 (문장이므로)
// 함수 선언식 (Function Declaration)
function add(a, b) {
    return a + b;
}

// 함수 표현식 (Function Expression)
const add = function(a, b) {
    return a + b;
};

// 화살표 함수 (Arrow Function — 함수 표현식의 한 형태)
const add = (a, b) => a + b;

호이스팅 차이

이것이 함수 선언식과 함수 표현식의 가장 중요한 차이입니다.

// O 함수 선언식 — 선언 전에 호출 가능
console.log(add(1, 2));  // 3 (정상 동작)

function add(a, b) {
    return a + b;
}
// X 함수 표현식 — 선언 전에 호출 불가
console.log(add(1, 2));  // ReferenceError: Cannot access 'add'

const add = function(a, b) {
    return a + b;
};
// X 화살표 함수 — 함수 표현식이므로 동일하게 불가
console.log(add(1, 2));  // ReferenceError

const add = (a, b) => a + b;

호이스팅 동작 원리

JavaScript 엔진이 코드를 실행하기 전에 먼저 선언을 끌어올림

[함수 선언식 — 전체가 호이스팅]
// 실제 코드                     // 엔진이 해석하는 순서
greet("홍길동");                 function greet(name) {
                                    return `안녕 ${name}`;
function greet(name) {           }
    return `안녕 ${name}`;       greet("홍길동");  // O 정상
}

[함수 표현식 — 변수 선언만 호이스팅, 할당은 그 자리]
// 실제 코드                     // 엔진이 해석하는 순서
greet("홍길동");                 let greet;  // 선언만 호이스팅 (TDZ)
                                greet("홍길동");  // X 에러
const greet = function(name) {
    return `안녕 ${name}`;       greet = function(name) {
};                                   return `안녕 ${name}`;
                                };

함수 정의 방식 전체 비교

// 1. 함수 선언식 (Function Declaration)
function add(a, b) {
    return a + b;
}

// 2. 함수 표현식 (Function Expression)
const add = function(a, b) {
    return a + b;
};

// 3. 기명 함수 표현식 (Named Function Expression)
const add = function addFn(a, b) {
    return a + b;
};
// addFn은 함수 내부에서만 접근 가능 (재귀 등에 사용)

// 4. 화살표 함수 (Arrow Function)
const add = (a, b) => a + b;

// 5. 즉시 실행 함수 (IIFE)
(function() {
    console.log("즉시 실행");
})();
방식호이스팅this 바인딩arguments 객체생성자 사용
함수 선언식O 전체동적 (호출 방식에 따라)OO new 가능
함수 표현식X 변수만동적 (호출 방식에 따라)OO new 가능
화살표 함수X 변수만정적 (상위 스코프 고정)XX new 불가

this 바인딩 차이

const obj = {
    name: "홍길동",

    // 함수 선언식/표현식 — this가 호출 객체를 가리킴
    greet: function() {
        console.log(this.name);  // "홍길동" (this = obj)

        // 내부 함수에서 this 문제
        setTimeout(function() {
            console.log(this.name);  // undefined (this = window)
        }, 100);
    },

    // 화살표 함수 — this가 선언 시점의 상위 스코프 고정
    greetArrow: function() {
        console.log(this.name);  // "홍길동"

        setTimeout(() => {
            console.log(this.name);  // "홍길동" (상위 this 유지)
        }, 100);
    }
};

함수 선언식의 주의점

조건문 안의 함수 선언식

// 비엄격 모드에서 브라우저마다 동작이 다를 수 있음
if (true) {
    function greet() {
        return "hello";
    }
}
greet();  // 브라우저마다 결과가 다를 수 있음

// O 함수 표현식으로 사용하는 것이 안전
let greet;
if (true) {
    greet = function() {
        return "hello";
    };
}
greet();  // "hello" (예측 가능)

같은 이름 함수 선언식 중복

function add(a, b) {
    return a + b;
}

function add(a, b) {
    return a * b;  // 나중 선언이 덮어씀
}

add(2, 3);  // 6 (곱셈으로 덮어써짐, 에러 없음)

// const 함수 표현식은 중복 시 에러 발생
const add = (a, b) => a + b;
const add = (a, b) => a * b;  // X SyntaxError: Identifier already declared

실무 사용 가이드

일반적인 권장 사항:

① 최상위 레벨의 유틸 함수 → 함수 선언식
   - 호이스팅 덕분에 코드 순서에 자유로움
   - 파일 하단에 선언하고 상단에서 호출 가능

② 콜백, 변수 할당, 모듈 export → 함수 표현식 / 화살표 함수
   - 호출 순서가 명확, 재할당 방지 (const)
   - 화살표 함수는 this가 고정되어 콜백에 적합

③ 메서드 정의 → 함수 표현식 또는 축약 문법
   - 객체/클래스의 메서드에 적합
// ① 유틸 함수 — 함수 선언식
function formatDate(date) {
    return date.toISOString().split("T")[0];
}

// ② 콜백 — 화살표 함수
const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

// ② 모듈 export — 화살표 함수 또는 함수 표현식
export const fetchUser = async (id) => {
    const response = await fetch(`/api/users/${id}`);
    return response.json();
};

// ③ 클래스 메서드 — 축약 문법
class UserService {
    findById(id) {
        return this.repository.find(id);
    }
}

CSLOG에서 보기