1. 고차 함수
1) 일급 객체(first-class object)
컴퓨터 프로그래밍 언어에서 일급 객체(first-class object)란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다. 보통 함수에 인자로 넘기기, 수정하기, 변수에 대입하기와 같은 연산을 지원할때 그것을 일급 객체라고 한다. (위키피디아)
📝 JavaScript의 대표적인 일급 객체, 함수의 특징
✅ 함수는 변수에 할당(assignment)할 수 있다.
const addNum = function(num1, num2) {
return num1 + num2;
}
let result = addNum(5, 10);
console.log(result); // 15
이러한 특성을 이용해 함수를 데이터(string, number 등)처럼 다룰 수 있고, 배열의 요소나 객체의 속성값으로도 저장할 수 있다.
함수가 객체의 속성값이 되는 경우, 이것을 메서드(method)라고 한다.
또한, 고차 함수(higher order function)는 아래와 같은 특징들을 갖고 있다.
✅ 함수는 다른 함수의 전달인자(argument)로 전달될 수 있다. (= 함수는 다른 함수를 전달인자로 전달 받을 수 있다)
function multiply2(num) {
return num * 2;
}
function multiplyNum(func, num) {
return func(num);
}
let result = multiplyNum(multiply2, 5);
console.log(result); // 10
콜백 함수(callback function)
: 다른 함수(caller)의 전달 인자(argument)로 전달 되는 함수.
위의 예시 코드에서는 multiply2가 multiplyNum의 콜백 함수이다.
함수 multiplyNum은 다른 함수를 인자로 받기 때문에 고차 함수이다.
✅ 함수는 다른 함수의 결과로서 리턴 될 수 있다.
function addFn(num1) {
return function (num2) {
return num1 + num2;
}
}
let result1 = addFn(5)(3);
console.log(result1); // 선언된 함수를 변수에 할당할수있다
let result2 = addFn(5);
let output = result2(3); // addFn이 리턴하는 함수를 변수에 저장할 수 있다
console.log(output);
커링 함수
: 함수를 리턴하는 함수. 논리 학자 하스켈 커리(Haskell Curry)의 이름을 땄다.
따로 이 용어를 사용하는 경우, 고차 함수라는 용어를 '함수를 전달인자로 받는 함수' 에만 한정해 사용하기도 한다.
정확하게 구분하자면 고차함수는 커링 함수를 포함한다.
2) 고차 함수를 사용하는 이유
추상화(abstraction)는 복잡한 어떤 것을 압축해서 핵심만 추출한 상태로 만드는 것이다.
고민할 것이 줄어들고 문제의 해결은 더 쉬워지는 것이 추상화의 이점이고, 추상화는 생산성을 향상시킬 수 있다.
추상화의 예시로서는 함수를 예로 들 수 있다.
함수는 자주 반복해서 사용하는 로직들을 별도로 모아 작성한 것이다. 그리고 이 함수로 얻은 추상화를 한단계 더 높인 것이 고차 함수이다.
함수는 값을 전달받아 값을 리턴하고, 값에 대한 논리는 감추어져있다. 이것이 값 수준에서의 추상화이다.
고차 함수는 함수를 전달받거나 함수를 리턴하고, 사고(함수)에 대한 복잡한 논리는 감추어져있다. 이것은 사고 수준에서의 추상화이다.
값 수준에서의 추상화는 단순히 값을 전달받아 처리하는 수준에 그치치만, 사고의 추상화는 함수, 즉 사고의 묶음을 전달받아서 처리하는 수준이다. 따라서 개발자는 고차함수를 통해 보다 더 높은 수준에서 생각할 수 있고 더 많은 효율성과 생산성을 얻을 수 있다.
3) filter
모든 배열의 요소 중에서 특정 조건을 만족하는 요소를 걸러내는 메서드.
arr.filter(callback(element))
배열의 각 요소가 특정 논리(콜백함수)로 판단했을때 참(true)일 경우 따로 분류한다.
📝 예제
// 장르가 영화인 객체만 모아 새로운 배열로 리턴하세요.
const list = [
{
title: 'Harry Potter And The Prisoner Of Azkaban',
genre: 'movie'
},
{
title: 'SHERLOCK',
genre: 'drama'
},
{
title: 'Knives Out',
genre: 'movie'
},
{
title: 'WEDNESDAY',
genre: 'drama'
},
{
title: 'Kingdom',
genre: 'drama'
},
{
title: 'Vivarium',
genre: 'movie'
},
];
let result = list.filter(el => el.genre === 'movie');
// 성적이 80점 이상인 학생들의 목록을 배열로 만들어 리턴하세요
const students = [
{
name: 'Harry',
score: 70,
},
{
name: 'Sherlock',
score: 100,
},
{
name: 'Wednesday',
secore: 99,
},
{
name: 'John',
score: 50
},
{
name: 'Anne',
score: 77
},
{
name: 'Lucy',
score: 80
},
{
name: 'Diana',
score: 95
},
];
let result = students.filter(el => el.score >= 80);
console.log(result);
4) map
배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환한다.
arr.map(callback(currentValue))
배열의 각 요소가 특정 논리(콜백함수)에 의해 다른 요소로 지정된다. 하나의 데이터를 다른 데이터로 매핑(mapping)할때 사용한다.
📝 예제
// 배열 내의 숫자에 2를 곱한 값의 배열을 만들기
const numbers = [2, 25, 87, 154, 45, 68, 9];
let result = numbers.map(el => el*2);
console.log(result);
// 짝수는 even, 홀수는 odd로 바꿔서 배열 리턴하기
const numbers = [7,5,4,20,65,21,32];
let result = numbers.map(el => el % 2 === 0 ? 'even' : 'odd');
console.log(result);
5) reduce
배열의 각 요소를 특정 방법(콜백함수)에 따라 원하는 하나의 형태로 응축한다.
arr.reduce(callback(accmulator, currentValue), initialValue)
초기값(initialValue)를 지정하지 않았을 경우, 배열의 0번째 인덱스의 요소가 초기값(accmulator)이 된다.
다시말해 초기값이 지정하지 않았을 경우에는 배열의 0번째 인덱스의 요소가 누적값(accmulator)의 기반이 되고, 배열의 1번째 인덱스의 요소가 현재값(currentValue)가 되어 연산한다.
초기값을 지정할 경우에는 지정된 초기값이 누적값의 기반이 되어 배열의 0번째 요소와 연산을 시작한다.
📝 예제
// 배열의 모든 값 더한 값을 리턴
const numbers = [1, 2, 3, 4, 5, 6, 7, 8 , 9];
console.log(numbers.reduce((acc, cur) => acc + cur));
// 중첩된 2차원 배열을 합쳐서 1차원 배열로 만들기
const flattened = [[0, 1], [2, 3], [4, 5]].reduce(
function(accumulator, currentValue) {
return accumulator.concat(currentValue);
},
[]
);
console.log(flattened);
*******
와... 오늘진짜 역대급으로 힘들었다....
배워야 할건 너무 많고, 이해는 빨리 되지도 않고, 그래서 시간이 너무 부족했다....ㅠㅠㅠㅠㅠㅠ
그래도 혼자서 다시 예제를 만들어보고 연습문제도 풀어보면서 복습해보니 조금 더 잘 적용할 수 있을 것 같다.
다만 궁금한 점이 있는데, map도 배열 내부의 요소들로 콜백함수의 내용을 적용하는 것이고, forEach나 for...of도 비슷한 동작을 한다고 생각이 되는데 뭐가 다른걸까? 이건... 주말에 알아봐야할것같다
지금 진짜 머리가 너무 아픔...
그래도 좀 더 일일회고를 적어보겠다
오늘 어려웠던 점 : 고차함수 이해가 어려웠음. 고차함수 내부에 클로저가 포함되어있다고 했는데, 클로저를 아직도 잘 모르겠어서 고차함수도 이해가 힘들었던거같다... 주말에는 꼭 클로저를 뽀개보겠음
오늘 좋았던 점 : 페어분들이 다 좋은 분들이셔서 짧은 시간이었지만 즐겁게 같이 과제할수있었다! 나는 조금 더 적극적인 자세가 필요하다고 생각되지만 그게 잘 안된다... 그래도 조금더 힘내볼것
'study > TIL' 카테고리의 다른 글
23.01.16 - 프로토타입 체인 (0) | 2023.01.16 |
---|---|
23.01.13 - 클래스와 인스턴스, 객체 지향 프로그래밍, 프로토타입과 클래스 (0) | 2023.01.13 |
23.01.08 - 유효성 검사, 이벤트 객체 (0) | 2023.01.08 |
23.01.05 - DOM, DOM으로 CRUD (0) | 2023.01.05 |
23.01.04 - 복습 및 추가 보완 (0) | 2023.01.04 |