Engineering
JavaScript 함수 핵심 패턴
JavaScript 함수 핵심 패턴 학습 내용을 정리한 백필 노트입니다.
이 글은 2025년 학습 기록을 블로그 형식으로 정리한 백필 노트입니다.
1. 함수의 기본 개념
1급 객체 (First-class Object)
JavaScript에서 함수는 '1급 객체'입니다. 이는 함수를 일반 데이터(값)처럼 다룰 수 있다는 의미입니다.
- 변수에 할당할 수 있다.
- 다른 함수의 인수로 전달할 수 있다.
- 다른 함수의 반환값으로 사용될 수 있다.
데이터로서의 함수와 호출
hello: 함수 자체(데이터, 객체)를 의미합니다.hello(): 함수를 호출(실행)하고 반환된 값을 의미합니다.
function hello() {
return 'Hello~'
}
console.log(hello) // ƒ hello() (함수 객체)
console.log(hello()) // 'Hello~' (함수 호출 후 반환된 문자열)
함수 선언문 vs 함수 표현식
-
함수 선언문 (Declaration):
function키워드로 시작하며, 이름이 있는(기명) 함수입니다.JavaScriptfunction hello() { /* ... */ } -
함수 표현식 (Expression): 변수에 함수를 할당하는 방식이며, 주로 이름이 없는(익명) 함수를 사용합니다.JavaScript
const hello = function() { /* ... */ };
호이스팅 (Hoisting)
함수 선언문은 유효 범위 최상단으로 끌어올려져, 선언보다 먼저 호출할 수 있습니다. 함수 표현식은 호이스팅되지 않습니다.
helloDeclaration(); // OK!
helloExpression(); // Error: Cannot access 'helloExpression' before initialization
function helloDeclaration() {
console.log('선언문 호이스팅');
}
const helloExpression = function() {
console.log('표현식');
};
반환(Return)과 종료
return키워드는 함수 외부로 데이터를 반환하고, 그 즉시 함수 실행을 종료합니다.return이 없거나return;만 있는 함수는undefined를 반환합니다. (보이드 함수)
2. 매개변수(Parameter) 처리 패턴
기본값 (Default Value)
매개변수에 인수가 전달되지 않거나 undefined가 전달되면, 설정된 기본값을 사용합니다.
function sum(a, b = 1) {
return a + b;
}
console.log(sum(2)); // 3
console.log(sum(2, 5)); // 7
구조 분해 할당 (Destructuring Assignment)
객체나 배열을 인수로 받을 때, 내부의 속성이나 요소를 직접 매개변수로 추출할 수 있습니다.
// 객체 구조 분해
const user = { name: 'HEROPY', age: 85 };
const getName = ({ name }) => name;
console.log(getName(user)); // 'HEROPY'
// 배열 구조 분해
const fruits = ['Apple', 'Banana', 'Cherry'];
const getSecond = ([, b]) => b;
console.log(getSecond(fruits)); // 'Banana'
나머지 매개변수 (Rest Parameter)
... (전개 연산자)를 사용하여 특정 매개변수 뒤의 모든 인수를 배열로 받을 수 있습니다.
function sum(a, b, ...rest) {
console.log(a, b, rest); // 1 2 [3, 4, 5]
return rest.reduce((acc, cur) => acc + cur, a + b);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
arguments 객체
함수 내부에서 사용 가능한 유사 배열 객체로, 함수로 들어온 모든 인수를 참조할 수 있습니다. (나머지 매개변수 사용을 권장)
3. 다양한 함수 생성 및 호출 방식
화살표 함수 (Arrow Function)
일반 함수보다 간결한 문법으로 함수를 작성할 수 있습니다.
function키워드와return을 생략할 수 있습니다.- 매개변수가 하나일 경우
()생략이 가능합니다. - 객체 리터럴을 반환할 때는
()로 감싸야 합니다. (() => ({ a: 1 })) - 주의: 일반 함수와
this키워드의 동작 방식이 다릅니다.
즉시실행함수 (IIFE)
함수를 정의함과 동시에 즉시 실행하는 문법으로, 전역 변수 오염 방지 및 정보 은닉에 사용됩니다.
// 이전 코드와의 충돌 방지를 위해 앞에 세미콜론(;)을 붙이는 것이 안전합니다.
;(async () => {
console.log('IIFE!');
const res = await fetch('URL');
// ...
})();
콜백 (Callback)
다른 함수의 인수로 전달되는 함수입니다. 비동기 처리나 특정 시점에 코드를 실행할 때 유용하게 사용됩니다.
function sum(a, b, callback) {
setTimeout(() => {
callback(a + b);
}, 1000);
}
sum(3, 7, function(value) {
console.log(value); // 1초 후 10 출력
});
호출 스케줄링 (Timers)
setTimeout(callback, 시간): 지정된 시간 후에 콜백을 한 번 호출.clearTimeout(ID)으로 취소.setInterval(callback, 시간): 지정된 시간마다 콜백을 반복 호출.clearInterval(ID)으로 취소.
주의: 불필요한 타이머는 메모리 누수 방지를 위해 반드시 취소해야 합니다.
재귀 (Recursion)
함수 내부에서 자기 자신을 다시 호출하는 기법입니다. 종료 조건이 없으면 스택 오버플로가 발생할 수 있습니다.
const getRootUser = user => {
if (user.parent) {
return getRootUser(user.parent); // 재귀 호출
}
return user; // 종료 조건
};
4. 스코프(Scope)와 컨텍스트(Context)
렉시컬 스코프 (Lexical Scope)
함수가 선언된 위치에 따라 상위 스코프가 결정되는 정적 스코프입니다. 함수는 선언될 때의 유효 범위를 기억합니다.
this 키워드
this는 함수가 호출되는 방식에 따라 동적으로 결정되는 특별한 식별자입니다.
| 함수 종류 | this 정의 | 스코프 |
| --- | --- | --- |
| 일반 함수 | 호출 위치에서 동적으로 결정 | 동적(Dynamic) |
| 화살표 함수 | 선언된 위치의 렉시컬 스코프에서 정적으로 결정 | 정적(Static) |
const user = {
name: 'Heropy',
getNameA() { // 일반 함수
return this.name; // this는 user 객체
},
getNameB: () => { // 화살표 함수
return this.name; // this는 선언된 위치의 스코프(예: window 또는 undefined)
}
};
console.log(user.getNameA()); // 'Heropy'
console.log(user.getNameB()); // undefined (브라우저 최상위 스코프에 name이 없으므로)
.call(), .apply(), .bind()
일반 함수의 this 값을 명시적으로 지정하여 호출할 수 있는 메소드입니다.
.call(this객체, 인수1, 인수2, ...): 함수를 즉시 호출..apply(this객체, [인수1, 인수2, ...]): 함수를 즉시 호출. (인수를 배열로 받음).bind(this객체, 인수1, ...):this가 고정된 새로운 함수를 반환. (즉시 호출하지 않음)
5. 고급 함수 패턴 및 개념
클로저 (Closure)
함수가 선언될 때의 렉시컬 환경을 기억하여, 함수가 외부에서 호출될 때도 해당 환경에 접근할 수 있는 특성입니다. 정보 은닉(private 변수 흉내)이나 상태 유지가 필요할 때 유용합니다.
function createCount() {
let c = 0; // 외부에서 접근 불가한 private 변수처럼 동작
return function () {
return (c += 1);
};
}
const count = createCount();
console.log(count()); // 1
console.log(count()); // 2
함수 커링 (Currying)
여러 인수를 받는 함수를, 인수를 하나씩 받는 여러 개의 함수로 나누는 기법입니다. 함수의 재사용성과 가독성을 높입니다.
// 커링 미적용
function myConsole(level, message) { console[level](message); }
// 커링 적용
function useConsole(level) {
return function(message) {
console[level](message);
}
}
const log = useConsole('log');
const warn = useConsole('warn');
log('Hello world~');
warn('Danger ahead!');
팩토리 함수 (Factory Function)
객체를 생성하여 반환하는 함수입니다. 객체 생성 로직을 캡슐화하고 재사용성을 높입니다.
고차 함수 (Higher-Order Function)
함수를 인수로 받거나(콜백), 함수를 반환하는 함수를 말합니다. .map(), .filter() 등 배열 메소드가 대표적인 고차 함수입니다.