자바스크립트 함수 심화: 선언, 표현식, 호이스팅 및 this 바인딩

함수 선언문과 함수 표현식

자바스크립트에서 함수는 특정 작업을 수행하기 위해 설계된 재사용 가능한 코드 블록입니다. 함수를 정의하는 방식은 크게 두 가지로 나뉩니다.

함수 선언문 (Function Declaration)

함수 선언문은 독립적인 구문으로 존재하는 함수 정의 방식입니다. function 키워드로 시작하며 반드시 함수 이름을 포함해야 합니다.

// 독립적인 구문으로 작성된 함수 선언문
function calculateArea(width, height) {
   return width * height;
}

// 중첩된 함수 선언문 예시
function setupEnvironment() {
   function initialize() {
      console.log('환경 초기화 완료');
   }
   initialize();
}

위 코드에서 calculateArea, setupEnvironment, initialize는 모두 독립적인 구문이므로 함수 선언문에 해당합니다.

함수 표현식 (Function Expression)

함수를 변수에 할당하는 방식을 함수 표현식이라고 합니다. 이 방식의 가장 큰 특징은 함수의 이름을 생략할 수 있다는 점이며, 이렇게 이름이 없는 함수를 익명 함수라고 부릅니다.

const calculateVolume = function(width, height, depth) {
   return width * height * depth;
};

위 예시에서는 이름이 없는 함수 객체가 생성되어 calculateVolume 변수에 참조됩니다. 따라서 calculateVolume() 형태로 호출할 수 있습니다.

함수 표현식은 콜백 함수로 자주 사용됩니다. 다른 함수의 인자로 전달되거나, 특정 함수의 결과값으로 반환될 수 있습니다.

function processData(handler) {
   handler();
}

processData(function() { 
   console.log('데이터 처리 시작'); 
});

function createFormatter() {
   return function(text) {
      console.log(`포맷된 텍스트: [${text}]`);
   };
}

const formatLog = createFormatter();
formatLog('자바스크립트');

위 코드에서 createFormatter는 내부의 익명 함수를 반환합니다. 이처럼 함수가 다른 함수를 반환하거나 외부 함수의 변수를 참조하는 구조는 클로저(Closure)의 기본이 됩니다.

호이스팅(Hoisting)과 익명 함수의 차이

선언문과 표현식은 실행 엔진이 코드를 해석하고 메모리에 할당하는 방식에서 결정적인 차이를 보입니다.

1. 호이스팅 (Hoisting)

호이스팅은 자바스크립트 엔진이 코드를 실행하기 전에 변수와 함수의 선언을 최상단으로 끌어올리는 동작을 말합니다.

console.log(greetUser('Alice'));

function greetUser(name) {
   return `안녕하세요, ${name}님!`;
}

함수 선언문은 전체 코드(함수 몸체 포함)가 호이스팅되므로, 정의되기 전에 호출해도 정상적으로 작동합니다.

하지만 블록 구문(예: if문) 내부의 함수 선언문은 브라우저 환경에 따라 다르게 동작할 수 있으며, 일반적으로 호이스팅되지 않거나 undefined로 처리되는 등 예측하기 어려운 동작을 유발할 수 있습니다.

let isAuthenticated = false;

if (isAuthenticated) {
   function showDashboard() {
      console.log('대시보드 표시');
   }
}

반면, 함수 표현식은 호이스팅되지 않습니다. 변수 선언 자체는 호이스팅되지만, 함수 객체의 할당은 해당 라인에 도달했을 때 이루어집니다.

console.log(multiplyNumbers(5, 3)); // TypeError 발생

var multiplyNumbers = function(a, b) {
   return a * b;
};

엔진은 multiplyNumbers 변수를 호이스팅하여 undefined로 초기화하지만, 함수 객체는 아직 할당되지 않았으므로 호출 시 오류가 발생합니다. 기명 함수 표현식을 사용하더라도 동일하게 적용됩니다.

2. 익명 함수 (Anonymous Functions)

함수 선언문은 반드시 이름을 가져야 하므로 문법 오류가 발생합니다. 반면 함수 표현식은 이름을 생략하여 익명 함수를 만들 수 있습니다. 이는 이벤트 리스너나 콜백 함수를 작성할 때 코드를 간결하게 유지하는 데 필수적인 기능입니다.

즉시 실행 함수 표현식 (IIFE)

IIFE(Immediately Invoked Function Expression)는 정의됨과 동시에 즉시 실행되는 함수를 의미합니다. 전역 스코프를 오염시키지 않고 독립적인 스코프를 형성할 때 유용하게 사용됩니다.

(function() {
   const config = { theme: 'dark', lang: 'ko' };
   console.log('초기 설정 로드:', config);
})();

// config 변수는 IIFE 내부 스코프에 갇혀 있으므로 외부에서 접근 불가

라이브러리나 모듈 패턴에서 전역 변수 충돌을 방지하기 위해 IIFE를 적극적으로 활용합니다.

this 키워드의 동작 원리

this는 자바스크립트에서 동적으로 바인딩되는 특수한 키워드입니다. 함수가 어떻게 호출되느냐에 따라 this가 가리키는 객체가 달라집니다.

메서드로서 호출될 때, this는 해당 메서드를 포함하고 있는 객체를 참조합니다.

const user = {
   role: 'Administrator',
   printRole: function() { 
      console.log(this.role); 
   }
};

user.printRole(); // 'Administrator' 출력

user.printRole()로 호출되었기 때문에 함수 내부의 thisuser 객체를 가리키게 됩니다. 객체 이름을 하드코딩하는 대신 this를 사용하면 객체명이 변경되더라도 코드를 수정할 필요가 없어 유지보수성이 높아집니다.

그러나 함수가 독립적으로 호출될 경우(비엄격 모드), this는 전역 객체(브라우저 환경에서는 window)를 참조하게 됩니다.

function showGlobalContext() {
   console.log(this);
}

showGlobalContext(); // Window 객체 출력

태그: JavaScript FunctionDeclaration FunctionExpression Hoisting IIFE

7월 25일 13:30에 게시됨