JavaScript에서 자주 쓰이는 고차 함수
JavaScript에는 이미 정의된 고차 함수들이 많습니다. 배열 메서드에서 특히 자주 사용됩니다.
1. forEach()란?
forEach()는 JavaScript 배열(Array)의 메서드로, 배열의 각 요소를 순회하며 주어진 함수를 실행하는 역할을 합니다.
즉, forEach()는 배열에 저장된 요소마다 한 번씩 특정 작업을 수행할 때 사용됩니다.
1) 기본 문법
array.forEach(callbackFunction(currentValue, index, array));
2) 매개변수 설명
- callbackFunction (필수): 각 배열 요소에서 실행할 함수
- currentValue (필수): 현재 처리 중인 배열 요소
- index (선택): 현재 요소의 인덱스
- array (선택): forEach()가 호출된 원본 배열
3) forEach()의 기본 사용법
const fruits = ["사과", "바나나", "포도"];
fruits.forEach(function (fruit) {
console.log(fruit);
});
- 화살표 함수(Arrow Function)를 사용하면 더 간결하게 작성할 수 있습니다.
fruits.forEach((fruit) => console.log(fruit));
사과
바나나
포도
4) forEach()의 다양한 활용법
- 배열 요소와 인덱스 함께 사용하기
const colors = ["빨강", "파랑", "초록"];
colors.forEach((color, index) => {
console.log(`${index + 1}번째 색상: ${color}`);
});
1번째 색상: 빨강
2번째 색상: 파랑
3번째 색상: 초록
- 객체 배열을 순회하며 특정 속성 출력하기
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 35 }
];
users.forEach((user) => {
console.log(`${user.name}의 나이는 ${user.age}세입니다.`);
});
Alice의 나이는 25세입니다.
Bob의 나이는 30세입니다.
Charlie의 나이는 35세입니다.
5) forEach() 사용 시 주의할점
break 또는 return 사용 불가능
- forEach()는 반복문이 아니라 콜백 함수를 실행하는 메서드이므로 break, continue, return을 사용할 수 없습니다.
- 만약 특정 조건에서 반복을 중단해야 한다면, forEach() 대신 for...of 또는 some(), every()를 사용해야 합니다.
const numbers = [1, 2, 3, 4, 5];
numbers.forEach((num) => {
if (num === 3) {
return; // 무시됨! (반복문이 중단되지 않음)
}
console.log(num);
});
1
2
4
5
2. map()이란?
map()은 JavaScript 배열(Array)의 메서드 중 하나로, 배열의 각 요소를 변환하여 새로운 배열을 생성하는 함수입니다.
기존 배열을 변경하지 않고, 새로운 배열을 반환한다는 점이 forEach()와의 큰 차이점입니다.
1) 기본 문법
const newArray = array.map(callbackFunction(currentValue, index, array));
매개변수 설명
- callbackFunction (필수): 각 배열 요소에서 실행할 함수
- currentValue (필수): 현재 처리 중인 배열 요소
- index (선택): 현재 요소의 인덱스
- array (선택): map()이 호출된 원본 배열
- map()은 새로운 배열을 반환하며, 원본 배열을 변경하지 않습니다.
2) map() 기본 사용법
- 배열의 각 요소를 변환하기
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(numbers); // [1, 2, 3, 4, 5] (원본 배열 유지)
- forEach()와 달리, map()은 새로운 배열을 반환합니다.
3) map()의 다양한 활용법
- 배열의 문자열 변환
const names = ["alice", "bob", "charlie"];
const capitalizedNames = names.map(name => name.toUpperCase());
console.log(capitalizedNames); // ["ALICE", "BOB", "CHARLIE"]
- map()을 사용하여 문자열을 변환할 수 있습니다.
- 객체 배열 변환하기
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 35 }
];
const userNames = users.map(user => user.name);
console.log(userNames); // ["Alice", "Bob", "Charlie"]
- 객체 배열에서 특정 속성만 추출할 때도 유용하게 사용할 수 있습니다.
- 인덱스를 활용하여 새로운 배열 만들기
const numbers = [10, 20, 30];
const indexedNumbers = numbers.map((num, index) => `Index ${index}: ${num}`);
console.log(indexedNumbers);
// ["Index 0: 10", "Index 1: 20", "Index 2: 30"]
- map()의 두 번째 매개변수인 index를 사용하여 배열 요소의 인덱스를 활용할 수도 있습니다.
4) map() 사용 시 주의할 점
- map()은 반드시 새로운 배열을 반환하므로, return을 생략하면 배열 요소가 undefined가 됩니다.
const numbers = [1, 2, 3];
const result = numbers.map(num => {
num * 2; // ❌ return을 생략함
});
console.log(result); // [undefined, undefined, undefined]
- 해결 방법: return을 추가하기
const result = numbers.map(num => num * 2);
console.log(result); // [2, 4, 6]
3. filter()란?
filter()는 JavaScript 배열 메서드 중 하나로, 특정 조건을 만족하는 요소만 걸러서 새로운 배열을 반환하는 함수입니다.
원본 배열을 변경하지 않고, 조건에 맞는 요소들만 포함하는 새로운 배열을 생성합니다.
1) 기본 문법
const newArray = array.filter(callbackFunction(currentValue, index, array));
매개변수 설명
- callbackFunction (필수): 각 배열 요소에서 실행할 함수
- currentValue (필수): 현재 처리 중인 배열 요소
- index (선택): 현재 요소의 인덱스
- array (선택): filter()가 호출된 원본 배열
- filter()는 true를 반환하는 요소만 새로운 배열에 포함합니다.
2) filter() 기본 사용법
- 짝수만 걸러내기
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = numbers.filter(num => num % 2 === 0);
console.log(evenNumbers); // [2, 4, 6]
- 특정 조건을 만족하는 객체 필터링
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 17 },
{ name: "Charlie", age: 30 }
];
const adults = users.filter(user => user.age >= 18);
console.log(adults);
// [{ name: "Alice", age: 25 }, { name: "Charlie", age: 30 }]
- 문자열 배열에서 특정 단어가 포함된 요소 찾기
const words = ["apple", "banana", "cherry", "avocado"];
const aWords = words.filter(word => word.startsWith("a"));
console.log(aWords); // ["apple", "avocado"]
- 중복 제거 (Set과 함께 활용)
const numbers = [1, 2, 2, 3, 4, 4, 5];
const uniqueNumbers = numbers.filter((num, index, arr) => arr.indexOf(num) === index);
console.log(uniqueNumbers); // [1, 2, 3, 4, 5]
- 배열에서 null 또는 undefined 값 제거
const mixedArray = [1, null, 2, undefined, 3, "", 4, 0, false];
const validValues = mixedArray.filter(value => value);
console.log(validValues); // [1, 2, 3, 4]
3) filter() 사용 시 주의할 점
- filter()는 항상 새로운 배열을 반환
const numbers = [1, 2, 3, 4, 5];
const filtered = numbers.filter(num => num > 2);
console.log(filtered); // [3, 4, 5]
console.log(numbers); // [1, 2, 3, 4, 5] (원본 배열 유지)
- filter() 에서 return을 생략하면 undefined가 반환됨
const numbers = [1, 2, 3, 4, 5];
const result = numbers.filter(num => {
num > 2; // ❌ return을 생략하면 항상 undefined가 반환됨
});
console.log(result); // []
- 해결 방법: return 추가
const result = numbers.filter(num => num > 2);
console.log(result); // [3, 4, 5]
4. reduce()란?
reduce()는 JavaScript 배열 메서드 중 하나로, 배열의 모든 요소를 하나의 값으로 줄이는 함수입니다.
이를 통해 배열을 순회하며 누적 계산을 수행할 수 있습니다.
- 배열의 총합 또는 곱 계산
- 배열에서 최댓값/최솟값 찾기
- 객체 배열을 그룹화 또는 통계 값 계산
- 배열을 다른 형식의 데이터로 변환
1) 기본 문법
const result = array.reduce(callbackFunction(accumulator, currentValue, index, array), initialValue);
매개변수 설명
- callbackFunction (필수): 배열의 각 요소에서 실행할 함수
- accumulator: 누적값 (이전 반복의 반환값)
- currentValue: 현재 처리 중인 배열 요소
- index (선택): 현재 요소의 인덱스
- array (선택): reduce()가 호출된 원본 배열
- initialValue (선택): accumulator의 초기값 (생략 시 배열의 첫 번째 요소 사용)
reduce()는 배열을 순회하며 누적 연산을 수행한 최종 결과를 반환합니다.
2) reduce() 기본 사용법
- 배열의총합 구하기
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 15
- 배열 요소의 곱 구하기
const numbers = [2, 3, 4];
const product = numbers.reduce((acc, num) => acc * num, 1);
console.log(product); // 24
- 최댓값/최솟값 찾기
const numbers = [10, 5, 8, 20, 3];
const max = numbers.reduce((acc, num) => (num > acc ? num : acc), numbers[0]);
const min = numbers.reduce((acc, num) => (num < acc ? num : acc), numbers[0]);
console.log(max); // 20
console.log(min); // 3
- 객체 배열에서 특정 속성 값 합산하기
const orders = [
{ item: "Laptop", price: 1000 },
{ item: "Phone", price: 500 },
{ item: "Tablet", price: 700 }
];
const totalPrice = orders.reduce((acc, order) => acc + order.price, 0);
console.log(totalPrice); // 2200
- 배열을 객체 형태로 그룹화
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 25 },
{ name: "David", age: 30 }
];
const groupedByAge = users.reduce((acc, user) => {
acc[user.age] = acc[user.age] || [];
acc[user.age].push(user);
return acc;
}, {});
console.log(groupedByAge);
/*
{
25: [{ name: "Alice", age: 25 }, { name: "Charlie", age: 25 }],
30: [{ name: "Bob", age: 30 }, { name: "David", age: 30 }]
}
*/
3) reduce() 사용 시 주의할 점
- 초기값을 지정하지 않으면 첫 번째 요소가 초기값이 됨
const numbers = [10, 20, 30];
const sum = numbers.reduce((acc, num) => acc + num); // 초기값 미설정
console.log(sum); // 60
- 빈 배열일 경우 초기값을 반드시 설정하세요.
const sum = numbers.reduce((acc, num) => acc + num, 0);
JavaScript 배열 메서드 비교 (forEach, map, filter, reduce)
forEach() | 배열을 순회하며 각 요소에 대해 특정 작업 수행 | ❌ 반환값 없음 (undefined) | ❌ 변경하지 않음 | 단순 반복 작업 (콘솔 출력, DOM 조작 등) |
---|---|---|---|---|
map() | 배열의 각 요소를 변환하여 새로운 배열 생성 | ✅ 새로운 배열 반환 | ❌ 변경하지 않음 | 모든 요소를 변환하고 싶을 때 (ex: 배열 값 변경) |
filter() | 조건을 만족하는 요소만 새로운 배열로 반환 | ✅ 새로운 배열 반환 | ❌ 변경하지 않음 | 특정 조건을 만족하는 요소만 추출하고 싶을 때 |
reduce() | 배열을 순회하며 값을 누적하여 하나의 결과값 반환 | ✅ 누적된 값 반환 | ❌ 변경하지 않음 | 총합, 평균, 객체 변환 등 데이터 축소 작업 |
고차 함수의 장점
- 코드의 재사용성 증가
고차 함수를 사용하면 반복적인 작업을 추상화하여 재사용 가능한 코드를 만들 수 있습니다. - 코드의 간결성
복잡한 작업을 간단한 함수 조합으로 표현할 수 있습니다. - 가독성 향상
작업의 의도가 명확해지고, 유지보수가 쉬워집니다. - 함수형 프로그래밍 구현 가능
고차 함수는 함수형 프로그래밍의 핵심 요소로, 불변성과 선언적 코드를 작성하는 데 필수적입니다.
고차 함수의 한계와 주의점
- 익명 함수 남용
너무 많은 익명 함수 사용은 가독성을 해칠 수 있습니다. 필요하면 함수 이름을 명시하세요. - 과도한 중첩
고차 함수를 많이 중첩해서 사용하면, 코드가 복잡해질 수 있습니다. - 성능
대규모 데이터에 대해 고차 함수를 사용할 경우, 성능 문제가 발생할 수 있습니다. 이런 경우, 효율적인 알고리즘 설계를 병행해야 합니다.
결론
고차 함수는 JavaScript의 강력함과 유연성을 보여주는 중요한 기능입니다.
코드를 더 읽기 쉽고 재사용 가능하게 만들어주며, 함수형 프로그래밍을 구현하는 데 필수적인 도구입니다.
자주 사용하는 배열 메서드(map, filter, reduce 등)부터 직접 고차 함수를 작성하며 활용법을 익혀보세요!
'JavaScript' 카테고리의 다른 글
[JavaScript] 비동기 프로그래밍 (Promise, async/await) (0) | 2025.01.31 |
---|---|
[JavaScript] ES6+ 문법 (1) | 2025.01.30 |
[JavaScript] 클로저(Closure) (0) | 2025.01.28 |
JavaScript 기본 문법 (0) | 2025.01.28 |
JavaScript에 대해서 (1) | 2025.01.28 |