| 구분 | 설명 |
|---|---|
| 일반 함수 | 숫자가 문자열 같은 값을 인자로 받아서 결과를 반환함 |
| 고차 함수 | 함수 자체를 인자로 받거나, 혹은 함수를 결과로 반환함 |
1. 함수를 인자로 받는다.
2. 함수를 리턴한다.
이 중 하나만 만족해도 고차 함수이다.
✅ 예시 1: 함수를 인자로 받는 고차 함수
function repeat(n, action) {
for (let i = 0; i < n; i++) {
action(i);
}
}
// 사용 예시
repeat(5, console.log);
repeat 함수는 숫자 n과 함수 action을 인자로 받음repeat(5, console.log)라고 하면, console.log가 action으로 전달됨 → i값 0~4까지 콘솔에 찍게 됨console.log라는 함수를 매개변수로 넘겼기 때문에 repeat는 고차 함수임✅ 예시 2: 함수를 반환하는 고차 함수
function greet(greeting) {
return function(name) {
return `${greeting}, ${name}!`;
};
}
const sayHello = greet("Hello");
console.log(sayHello("Hyunjin")); // Hello, Hyunjin!
const sayGoodBye = greet("Good Bye");
console.log(sayGoodBye("Kim")); // Good Bye, Kim!
greet("Hello")는 새로운 함수를 리턴함"Hello, ${name}!"을 만들어 줌greet는 고차 함수임| 함수 | 설명 | 예시 |
|---|---|---|
map | 배열 요소 각각을 변형해서 새 배열 생성 | arr.map(x => x * 2) |
filter | 조건에 맞는 요소만 골라서 새 배열 생성 | arr.filter(x => x > 0) |
reduce | 배열 요소를 누적해서 하나의 값으로 | arr.reduce((a, b) => a + b) |
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2); // [2, 4, 6, 8, 10]
const even = numbers.filter(num => num % 2 === 0); // [2, 4]
const sum = numbers.reduce((acc, cur) => acc + cur, 0); // 15
➡️ 모두 함수를 인자로 받는 고차 함수임
✅ 예시 1: map을 쓰지 않은 코드 vs. 고차 함수(map)를 사용한 코드
일반 방식 (반복문)
const numbers = [1, 2, 3, 4, 5];
const doubled = [];
for (let i = 0; i < numbers.length; i++) {
doubled.push(numbers[i] * 2);
}
console.log(doubled); // [2, 4, 6, 8, 10]
고차 함수 사용 방식 (map)
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
✅ 예시 2: filter를 쓰지 않은 코드 vs. 고차 함수(filter)를 사용한 코드
일반 방식 (반복문)
const scores = [90, 55, 78, 30, 88];
const passed = [];
for (let i = 0; i < scores.length; i++) {
if (scores[i] >= 60) {
passed.push(scores[i]);
}
}
console.log(passed); // [90, 78, 88]
고차 함수 사용 방식 (filter)
const scores = [90, 55, 78, 30, 88];
const passed = scores.filter(score => score >= 60);
console.log(passed); // [90, 78, 88]
➡️ 이처럼 고차 함수를 사용하면 반복문, 조건문, 임시 변수 선언 없이 한 줄로 같은 결과를 얻을 수 있음
여행 기간(시작일, 종료일)을 수정하는 함수를 고차 함수로 구현하였다.
const handleDateChange = (key: 'startDate' | 'endDate') => (e: React.ChangeEvent<HTMLInputElement>) => {
setTravelPeriod(prev => ({ ...prev, [key]: e.target.value }));
}
위 함수를 이해하기 위해서 위 함수와 관련 있는 코드를 설명한다.
const [travelPeriod, setTravelPeriod] = useState({
startDate: '',
endDate: '',
});onChange 속성에 handleDateChange 함수를 연결하고 있다.<input
type="date"
value={travelPeriod.startDate}
onChange={handleDateChange("startDate")} // 👈 이 부분 주목
min={today}
/>onChange 속성에 handleDateChange 함수를 연결하고 있다.<input
type="date"
value={travelPeriod.endDate}
onChange={handleDateChange("endDate")} // 👈 이 부분 주목
min={travelPeriod.startDate || today}
/>이제 다시 handleDateChange 고차 함수를 이해해보자.
const handleDateChange = (key: 'startDate' | 'endDate') => (e: React.ChangeEvent<HTMLInputElement>) => {
setTravelPeriod(prev => ({ ...prev, [key]: e.target.value }));
};
이 함수는 고차 함수(Higher-Order Function)로,
동작 방식
<input onChange={handleDateChange('startDate')} />
handleDateChange('startDate') 호출
👉 "startDate"라는 값을 받아서
👉 아래와 같은 onChange 핸들러 함수를 만들어 반환함
(e) => {
setTravelPeriod(prev => ({ ...prev, startDate: e.target.value }));
}
👉 즉, handleDateChange 함수 자체는 이벤트 핸들러를 만들어내는 고차 함수이지, 이벤트 핸들러가 아님
이 반환된 함수가 onChange에 전달되어
👉 input의 값이 바뀔 때마다 실행되는 이벤트 핸들러 역할을 하게 됨
위 구조를 쓰는 이유
| 장점 | 설명 |
|---|---|
| 재사용성 | 시작일/종료일 모두 하나의 함수로 처리 가능 (key만 바꾸면 됨) |
| 가독성 | 불필요하게 핸들러를 2개 만들 필요 없음 |
| 객체 상태 유지 | prev => ({ ...prev, [key]: value })는 기존 값을 보호하면서 변경하는 패턴 |
만약 이렇게 안 쓰면 코드가 중복됨
const handleStartDateChange = (e) => {
setTravelPeriod(prev => ({ ...prev, startDate: e.target.value }));
};
const handleEndDateChange = (e) => {
setTravelPeriod(prev => ({ ...prev, endDate: e.target.value }));
};
💡 위 함수들을 하나로 줄이기 위해 key를 매개변수로 받는 고차함수를 쓴 것임