코드스테이츠

1/12 일일정리 고차함수

강물둘기 2023. 1. 12. 20:03

일급 객체

일급 객체란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다. - 위키백과

아래와 같은 조건을 만족하면 일급 객체라고 할 수 있다. 

⓵ 무명의 리터럴로 생성할 수 있다. 즉, 런타임에 생성이 가능하다.

⓶ 변수나 자료구조(객체 배열 등)에 저장할 수 있다.

⓷ 함수의 매개변수에 전달할 수 있다.

⓸ 함수의 반환값으로 사용할 수 있다.

(- 이웅모 , 모던 자바스크립트 Deep Dive , 위키북스 , 2020 책에서 발췌)

 

대표적으로 Javascript의 함수가 일급 객체이다.

 

고차함수

고차 함수(higher order function)는 함수를 전달인자(argument)로 받을 수 있고, 함수를 리턴할 수 있는 함수다.

이때 다른 함수(caller)의 전달인자(argument)로 전달되는 함수를 콜백 함수(callback function)라고 한다.

콜백 함수를 전달받은 고차 함수는 함수 내부에서 이 콜백 함수를 호출할 수 있고 조건에 따라 콜백 함수의 실행 여부를 결정할 수도 있다. 아예 호출하지 않을 수도 있고, 여러 번 실행할 수도 있다.

함수를 리턴하는 함수를 커링 함수라고 부르는데, 커링 함수는 고차 함수의 일종이다.

//콜백함수를 전달받는 고차함수
const increase = function(value) {
	return value + 1;
    }
    
const apply = function(callback, value) {
	return callback(value);
    }
// increase함수는 콜백함수, apply함수는 고차함수
console.log(apply(increase, 9)); // 10


//커링 함수
function add(a){
  return function(b){
    return console.log(a+b);
  }
}
add(5)(6);	// 11

 

내장 고차 함수

filter

filter 메서드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환합니다. - MDN

filter 메서드는 콜백함수를 인자로 받고 콜백함수가 리턴하는 값이 true인 경우 새로운 배열의 인자로 만들고, false인 경우 버린다.

let arr = [1,2,3,4,5,6,7];

function isOdd(num){
  if(num % 2 === 1) return true;
  return false;
}

let result = arr.filter(isOdd);
console.log(result);	// [1,3,5,7]

 

map

map 메서드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환합니다. - MDN

배열의 요소를 하나하나 받아서 map에 인자로 전달된 함수를 실행하고 그 결과 값으로 새로운 배열을 만든다.

const array1 = [1, 4, 9, 16];

const map1 = array1.map(x => x * 2);

console.log(map1);	// [2, 8, 18, 32]

 

reduce

reduce 메서드는 배열의 각 요소에 대해 주어진 리듀서 (reducer) 함수를 실행하고, 하나의 결과값을 반환합니다. -MDN

const arr = [1,2,3,4,5];

const sum = arr.reduce(
  (acc, value) => acc + value
  ,0);

console.log(sum);	// 15

 

이 3가지 이외에도 많은 내장 고차함수가 있다. 필요할 때 찾아서 쓸 것.

 

 

코플릿 문제풀이

페어와 같이 코플릿 문제 풀이를 진행했다.

어려웠던게 27번 문제 배열 내 가장 긴 문자열을 리턴하는 문제였다.

우리는 map으로 각 요소의 길이를 갖는 배열을 따로 만들어 내림차순으로 정렬하면 0번 index의 값이 가장 길이가 긴 문자열 이므로

arr2[0] 과 같은 값을 갖는 문자열을 다시 찾는 방식으로 코드를 작성했다.

function getLongestElement(arr) {
  if(arr.length === 0) return '';
  // 각 요소 길이를 가지는 배열 생성
  let arr2 = arr.map(function(a){
    return a.length;
  })

  // 내림차순 정렬
  arr2.sort(function(a,b){
    return b-a;
  })
  // 정렬한 배열 0번 index의 값과 같은 길이를 가지는 문자열 찾기
  let result =  arr.filter(function(a){
     return a.length === arr2[0];
   })
  return result[0];
}

 

그런데 풀이를 보니 생각보다 훨씬 간단한 코드였다.

function getLongestElement(arr) {
  return arr.reduce(function (a, b) {
    if (a.length >= b.length) {
      return a;
    } else {
      return b;
    }
  }, '');
}

reduce를 사용해서 문자열 길이 비교도 가능하다는 것을 처음 알았다. 생각보다 reduce의 활용 방식이 다양하다는 것을 느꼇다.

그리고 좀 더 알고리즘 적인 사고방식을 연습 해봐야 겠다는 생각이 들었다.