[ 고차함수 (Higher-order function) ]
함수형 프로그래밍에서 다른 함수를 인자로 받거나, 함수를 결과로 반환하는 함수. (추상화)
[ 함수를 인자로 받는 고차함수 ]
ex) 자바스크립트 배열 메소드 map( ), filter( ), reduce( )
( TypeScript 의 타입정의 )
* Array.prototype.map
callbackfn (콜백함수) 는 세가지 인자(value, index, array)를 받음. *value 필수
- value : 처리중인 배열 요소의 값 / index : 처리중인 배열 요소의 인덱스 / array : 메서드가 호출된 (원본)배열
- thisArg ** : 콜백함수 내에서 'this'키워드로 사용될 객체를 명시적으로 지정.
- => U : 콜백함수가 반환할 타입.
- U[] : 콜백 함수의 반환값. (콜백함수의 로직(조건)에 따라 새로 생성된 배열)
const numbers = [1, 2, 3, 4];
const strings = numbers.map((value, index) => `Number ${value} at index ${index}`);
console.log(strings);
// 출력: ["Number 1 at index 0", "Number 2 at index 1", "Number 3 at index 2", "Number 4 at index 3"]
=> 원본 배열은 변경하지 않고, 콜백 함수가 인자로 받은 value, index에 대해 변환된 요소를 포함하는 새 배열 반환.
* thisArg
const team = {
members: ['Jane', 'Bill'],
teamName: 'Super Squad',
getTeamMembers() {
return this.members.map(function(member) {
return `${member} is on team ${this.teamName}`;
}, this); // 여기서 thisArg로 this를 전달
}
};
console.log(team.getTeamMembers());
// 출력: ["Jane is on team Super Squad", "Bill is on team Super Squad"]
=> thisArg 로 'this'를 전달함으로서 콜백함수 내부의 'this'는 'team'의 객체를 가리키게 된다.
따라서 'this'를 통해 'team'의 객체인 'member'와 'teamName' 속성에 접근 가능
thisArg 를 전달하지 않은 경우.
const team = {
members: ['Jane', 'Bill'],
teamName: 'Super Squad',
getTeamMembers() {
return this.members.map(function(member) {
return `${member} is on team ${this.teamName}`; // TypeError: Cannot read properties of undefined (reading 'teamName')
}); // thisArg가 없음
}
};
console.log(team.getTeamMembers());
=> 콜백함수 내부의 'this'는 기본적으로 전역객체를 가르키거나 'undefined' (엄격모드에서)가 된다.
* Array.prototype.filter
predicate (콜백함수) 는 세가지 인자( value, index, array)를 받음. ( * predicate 함수 : boolean값을 반환하는 함수)
- value : 처리중인 배열 요소의 값 / index : 처리중인 배열 요소의 인덱스 / array : 메서드가 호출된 (원본)배열
- thisArg ** : 콜백함수 내에서 'this'키워드로 사용될 객체를 명시적으로 지정.
- => unknown : 콜백함수의 반환 타입이 true/false 이지만 타입안정성 보장을 위해 'unknown'으로 설정.
( * unknown : 안전한 타입_모든 타입의 상위 타입 )
- T[] : 콜백 함수의 반환값. (콜백함수의 로직(조건)에 따라 새로 생성된 배열)
const people = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 20 },
{ name: "Charlie", age: 23 }
];
const adults = people.filter(person => person.age >= 21);
console.log(adults);
// [{ name: "Alice", age: 25 }, { name: "Charlie", age: 23 }]
=> 원본 배열은 변경하지 않고, 콜백 함수가 인자로 받은 value, index에 대해 필터링된 요소를 포함하는 새 배열 반환.
predicate함수가 true를 반환하면 해당 요소는 결과 배열에 포함되고, false를 반환하면 포함되지 않는다.
* Array.prototype.reduce
( 초기값과 배열요소값 타입이 같은 경우 'T' )
callbackfn (콜백함수) 는 네가지 인자( previousValue, currentValue, currentIndex, array)를 받음.
- previousValue : 초기값 / 이전 콜백 호출의 반환값
- currentValue : 처리중인 배열 요소의 값
- currentIndex : 처리중인 배열 요소의 인덱스
- array : 메서드가 호출된 (원본)배열
- => T : 콜백함수의 반환 타입이 true/false 이지만 타입안정성 보장을 위해 'unknown'으로 설정.
- initialValue: T : 초기값 (첫번째 콜백 호출에서 previousValue 로 사용), 없는 경우 배열의 첫번째 요소를 사용.
- T : 콜백 함수의 반환값.
* 초기값(initialValue) 없는 경우
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((previousValue, currentValue) => {
return previousValue + currentValue;
});
console.log(sum);
// 결과: 15
=> 초기값이 없기 때문에 배열의 첫번째 요소인 1을 초기값으로 사용.
(배열은 최소 하나의 요소를 가져야한다. 배열이 비어있다면 'TypeError' 발생)
* 초기값(initialValue) 있는 경우 (동일 타입)
const factors = [2, 4, 6, 8, 10];
const product = factors.reduce((previousValue, currentValue) => {
return previousValue * currentValue;
}, 1); // 초기값 1으로 설정
console.log(product); // 결과: 3840
=> 초기값 1부터 연산 시작. (곱셉연산이기 때문에 초기값이 0이라면 누적연산 결과가 0이된다.)
(빈 배열인 경우)
const numbers = [];
const sum = numbers.reduce((previousValue, currentValue) => {
return previousValue + currentValue;
}, 0); // 초기값으로 0을 설정
console.log(sum);
// 결과: 0
=> 배열이 비어있기 때문에 콜백함수가 호출되지 않고 초기값 0을 그대로 반환.
( 초기값( 'U' )과 배열요소값( 'T' ) 타입이 다른 경우 )
callbackfn (콜백함수) 는 네가지 인자( previousValue, currentValue, currentIndex, array)를 받음.
- previousValue : 초기값 / 이전 콜백 호출의 반환값
- currentValue : 처리중인 배열 요소의 값
- currentIndex : 처리중인 배열 요소의 인덱스
- array : 메서드가 호출된 (원본)배열
- => U : 콜백함수의 반환 타입이 true/false 이지만 타입안정성 보장을 위해 'unknown'으로 설정.
- initialValue: U : 초기값 (첫번째 콜백 호출에서 previousValue 로 사용), 없는 경우 배열의 첫번째 요소를 사용.
- U : 콜백 함수의 반환값. (콜백함수의 로직(조건)에 따라 새로 생성된 배열)
* 초기값(initialValue) 있는 경우 (다른 타입)
(객체연산)
const items = [{price: 10}, {price: 20}, {price: 30}];
const total = items.reduce((acc, item) => acc + item.price, 0); // 초기값 0
console.log(total);
// 60
=> 초기값은 0 (Number), prev는 숫자(Number), 배열요소값은 객체 (Object), 연산결과는 60 (Number)
(문자열 누적)
const numbers = [1, 2, 3, 4, 5];
const concatenatedString = numbers.reduce((prev, curr) => prev + curr.toString(), "");
console.log(concatenatedString);
// 결과: "12345"
=> 초기값은 "" (빈문자열_String), prev는 문자열(String), 배열요소값은 숫자(Number), 연산결과는 문자열(String)
(객체 누적)
const items = [
{ name: "Apple", price: 1 },
{ name: "Banana", price: 2 },
{ name: "Cherry", price: 3 }
];
const totalPrice = items.reduce((total, item) => total + item.price, 0);
console.log(totalPrice);
// 결과: 6
=> 초기값은 0 (Number), prev(total)는 숫자(Number), 배열요소값은 객체(Object), 연산결과는 숫자(Number)
(객체 변환)
const products = [
{ name: "Apple", price: 1 },
{ name: "Banana", price: 2 },
{ name: "Cherry", price: 3 }
];
const productCatalog = products.reduce((catalog, product) => {
catalog[product.name] = product.price;
return catalog;
}, {});
console.log(productCatalog);
// 결과: { Apple: 1, Banana: 2, Cherry: 3 }
=> 초기값은 {} (빈객체_Object), prev(catalog)는 객체(Object), 배열요소값은 객체(Object), 연산결과는 객체(Object)
** 초기값과 연산결과의 데이터 타입은 같아야함 **
[참고블로그]
'JavaScript > 공부공부' 카테고리의 다른 글
[JS] 배열값 비교 (include, '===') / Java_List 비교 (0) | 2024.06.19 |
---|---|
[JS] 고차함수 (2) closure, currying (0) | 2024.06.15 |
[JS] 비구조화 할당 (destructuring assignment) 문법 (2) | 2024.05.18 |
[JS] previousElementSibling & previousSibling / 삼항연산자 / Truthy & Falsy (0) | 2024.04.10 |
[JS] Select / Option 태그 (0) | 2024.03.17 |