내장 고차 함수 이해하기

자바스크립트에는 기본적으로 내장(built-in)되어 있는 고차 함수들이 있습니다. 바로 배열 메소드들 중 일부가 고차 함수에 해당합니다. 이 중 하나인 filter에 대해서 학습해 보겠습니다.

배열의 filter 메소드는 배열의 요소 중 특정 조건을 만족하는 요소들만을 걸러내는(filter) 메소드입니다. 예를 들어, 수(number)를 요소로 갖는 배열 중 짝수만을 걸러내거나, 18 보다 작은 수만을 걸러내는 식입니다. 문자열(string)을 요소로 갖는 배열 중 길이가 10 이하인 문자열만 걸러내거나, 'korea'만 걸러낼 수도 있습니다.

// 아래 코드에서 '짝수'와 '길이 5 이하'는 문법 오류(syntax error)에 해당합니다.
// 의미만 이해하도록 합니다.
let arr = [1, 2, 3, 4];
let output = arr.filter(짝수);
console.log(output); // ->> [2, 4]

arr = ['hello', 'code', 'states', 'happy', 'hacking'];
output = arr.filter(길이 5 이하)
console.log(output); // ->> ['hello', 'code', 'happy']

여기서 걸러내는 기준이 되는 특정 조건은 함수 형태로 filter 메소드의 인자로 전달되어야 합니다. filter 메소드는 (걸러내기 위한 조건을 명시한) 함수를 인자로 취하기 때문에 고차 함수입니다. filter 메소드가 동작하는 방식을 조금 더 자세히 살펴보면 아래와 같습니다.

// 아래 코드는 정확한 표현 방식은 아닙니다.
// 의미만 이해하도록 합니다.

let arr = [1, 2, 3];
// 배열의 filter 메소드는 함수를 인자로 받는 고차 함수입니다.
// arr.filter를 실행하면 내부적으로 arr에 접근할 수 있다고 생각해도 됩니다.
arr.filter = function (arr, func) {
  const newArr = [];
  for (let i = 0; i < arr.length; i++) {
    // filter에 인자로 전달된 콜백 함수는 arr의 각 요소를 전달받아 호출됩니다.
    // 콜백 함수가 true를 리턴하는 경우에만 새로운 배열에 추가됩니다.
    if (func(arr[i]) === true) {
      newArr.push(this[i]);
    }
  }
  // 콜백 함수의 결과가 true인 요소들만 저장된 배열을 리턴합니다.
  return newArr;
};

// 보다 정확한 정의
// Immersive 과정에서 프로토 타입과 this를 학습하신 후에
// 아래 코드를 이해하시기 바랍니다.
// Array.prototype.filter = function(func) {
//   const arr = this;
//   const newArr = []
//   for(let i = 0; i < arr.length; i++) {
//     if (func(arr[i]) === true) {
//       newArr.push(this[i])
//     }
//   }
//   return newArr;
// }

filter 메소드는 인자로 전달되는 콜백 함수에 배열의 요소를 다시 전달합니다. 콜백 함수는 전달받은 배열의 요소를 받아 (조건에 따라) 참(true) 또는 거짓(false)을 리턴해야 합니다. (적어도 filter 메소드는 이런 함수를 기대하고 있습니다.) 이 점을 반영하여 처음 본 코드를 완성하면 아래와 같습니다.

// 함수 표현식
const isEven = function (num) {
  return num % 2 === 0;
};

let arr = [1, 2, 3, 4];
// let output = arr.filter(짝수);
// '짝수'를 판별하는 함수가 조건으로서 filter 메소드의 인자로 전달됩니다.
let output = arr.filter(isEven);
console.log(output); // ->> [2, 4]

const isLteFive = function (str) {
  // Lte = less then equal
  return str.length <= 5;
};

arr = ['hello', 'code', 'states', 'happy', 'hacking'];
// output = arr.filter(길이 5 이하)
// '길이 5 이하'를 판별하는 함수가 조건으로서 filter 메소드의 인자로 전달됩니다.
let output = arr.filter(isLteFive);
console.log(output); // ->> ['hello', 'code', 'happy']

자기 주도 학습