[JS] 8. 고차함수




1. 고차함수

  • 하나 이상의 함수를 매개변수로 취하거나 함수를 결과로 반환하는 함수
  • 매개변수로 전달되는 함수는 콜백 함수(Callback function)
  • 대표 배열 조작 메서드
  • 임의 정렬 : Array.sort(callback func)
  • 반복 작업 : Array.forEach()
  • 콜백함수 결과 배열 반환 : Array.map()
  • 조건 만족하는 하나의 값 반환 : Array.find()
  • 조건 만족하는 값 배열로 반환 : Array.filter()
  • 누적 결과 값 반환 : Array.reduce()

sort() 문제와 한계점 🤔

let nums = [1, -1, 4, 0, 2, 3, 10, 20, 12];

console.log(nums.sort());
// [-1, 0, 1, 10, 12, 2, 20, 3, 4];
console.log(nums.reverse())
// [(4, 3, 20, 2, 12, 10, 1, 0, -1)];

let fruits = ["apple", "Orange", "orange", "melon"]

console.log(fruits.sort())
//[ 'Orange', 'apple', 'melon', 'orange' ]
console.log(fruits.reverse())
//[ 'orange', 'melon', 'apple', 'Orange' ]
  • 문제점 : 일의 자리 4가 10의 자리보다 뒤쪽에 정렬
  • 원인 : sort 메서드로 정렬될 때 배열의 요소가 일시적으로 문자열로 변경되어 발생
  • 한계점 : 대소문자 구분 없이 정렬하고 싶지만, 대소문자로 구분되어 정렬


sort 숫자 정렬시 해결법

let nums = [1, -1, 4, 0, 2, 3, 10, 20, 12];

console.log(nums.sort());
// [-1, 0, 1, 10, 12, 2, 20, 3, 4];
console.log(nums.reverse());
// [(4, 3, 20, 2, 12, 10, 1, 0, -1)];

// 1 -1 >> 1-(-1) > 0 >> 자리가 바껴서 -1 1
let ascending_order = function (x, y) {
  return x - y;
};

let descending_order = function (x, y) {
  return y - x;
};

console.log(nums.sort(ascending_order))
//[(-1, 0, 1, 2, 3, 4, 10, 12, 20)];
console.log(nums.sort(descending_order))
//[(20, 12, 10, 4, 3, 2, 1, 0, -1)];
  • reverse 는 cb 받지 못한다.
  • Array.sort() 특징 다시 찾아보기 🤔🤔
  • x - y > 0 : 자리 바꿔서 앞에 수가 가장 작은 수로 정렬된다.
  • 해당 작업이 반복되서 내부적으로 정렬을 한다. (작은 숫자가 앞으로)


sort 문자 정렬시 해결법

let ascending_order = function (x, y) {
  x = x.toUpperCase();
  y = y.toUpperCase();

  if (x > y) return 1;
  else if (y > x) return -1;
  else return 0;
};

let descending_order = function (x, y) {
    x = x.toUpperCase();
    y = y.toUpperCase();
  
    if (x < y) return 1;
    else if (y < x) return -1;
    else return 0;
};

let fruits = ["apple", "Orange", "orange", "melon"]

console.log(fruits.sort(ascending_order))
//[ 'apple', 'melon', 'Orange', 'orange' ]
console.log(fruits.reverse(descending_order))
//[ 'orange', 'Orange', 'melon', 'apple' ]


sort 숫자, 문자 공용화 (ascending_order, descending_order)

let ascending_order = function (x, y) {
  if (typeof x === "string") x = x.toUpperCase();
  if (typeof y === "string") y = y.toUpperCase();

  return x > y ? 1 : -1;
};

let descending_order = function (x, y) {
  if (typeof x === "string") x = x.toUpperCase();
  if (typeof y === "string") y = y.toUpperCase();

  return x < y ? 1 : -1;
};

let nums = [1, -1, 4, 0, 2, 3, 10, 20, 12];

console.log(nums.sort(ascending_order));
// [-1, 0, 1, 10, 12, 2, 20, 3, 4];
console.log(nums.reverse(descending_order));
// [(4, 3, 20, 2, 12, 10, 1, 0, -1)];

let fruits = ["apple", "Orange", "orange", "melon"];

console.log(fruits.sort(ascending_order));
//[ 'apple', 'melon', 'Orange', 'orange' ]
console.log(fruits.reverse(descending_order));
//[ 'orange', 'Orange', 'melon', 'apple' ]



2. 그 외 고차 함수

forEach()

let nums = [1,2,3]

for (let i = 0; i < nums.length; i++){
    console.log(nums[i])
}

nums.forEach(function (i) {
    console.log(i)
    // 1 2 3
})
  • 배열 요소 별 콜백 함수 각각에 실행 : Array.forEach(function(item, index, array){})
  • item : 배열 요소
  • index : 배열 위치
  • array : 배열


map()

let nums = [1, 2, 3, 4, 5]
let use_for_loop = []

for (let i = 0; i < nums.length; i++) {
    use_for_loop.push(nums[i] * 2)
}
console.log(use_for_loop)
//[ 2, 4, 6, 8, 10 ]

let use_map = nums.map(function (item) {
    return item * 2
})

console.log(use_map)
//[ 2, 4, 6, 8, 10 ]
  • 배열 요소 별로 함수를 호출하고 그 결과를 배열로 반환 : Array.map(function(item, index, array){})
  • item : 배열 요소
  • index : 배열 위치
  • array : 배열


find()

let users = [
  { name: "bob", age: 17, job: false },
  { name: "elice", age: 20, job: false },
  { name: "john", age: 37, job: true },
];

let find_job = users.find(function (user) {
  console.log(user);
  // 아래의 객체들이 한번씩 순환. bob일 경우 bob만 찾고 return
  // { name: 'bob', age: 17, job: false }
  // { name: 'elice', age: 20, job: false }
  // { name: 'john', age: 37, job: true }
  return user.job == false;
});

console.log(find_job);
//{ name: 'bob', age: 17, job: false }

let find_age = users.find(user => user.age == 37)
console.log(find_age)
//{ name: 'john', age: 37, job: true }
  • 콜백 함수의 조건을 만족하는, 단 하나의 값만 반환 : Array.find(function(item, index, array){})
  • item : 배열 요소
  • index : 배열 위치
  • array : 배열


filter()

let users = [
  { name: "bob", age: 17, job: false },
  { name: "elice", age: 20, job: false },
  { name: "john", age: 37, job: true },
];

let filter_job = users.filter(function (user) {
  console.log(user);
  // 아래의 객체들이 한번씩 순환. bob일 경우 bob만 찾고 return
  // { name: 'bob', age: 17, job: false }
  // { name: 'elice', age: 20, job: false }
  // { name: 'john', age: 37, job: true }
  return user.job == false;
});

console.log(filter_job);
//[
//     { name: 'bob', age: 17, job: false },
//     { name: 'elice', age: 20, job: false }
//   ]

let filter_age = users.filter(user => user.age > 17)
console.log(filter_age)
// [
//     { name: 'elice', age: 20, job: false },
//     { name: 'john', age: 37, job: true }
//   ]
  • 콜백 함수의 조건을 만족하는 값을 배열로 반환 : Array.filter(function(item, index, array){})
  • item : 배열 요소
  • index : 배열 위치
  • array : 배열


reduce()

let nums = [1, 2, 3, 4, 5];
let call_cnt = 0;

console.log("result\tvalue\tindex");
let sum = nums.reduce(function (accumulator, item, index, array) {
  console.log(accumulator, "\t\t", item, "\t\t", index);
  call_cnt++;
  return accumulator + item;
});

console.log(call_cnt)
console.log(sum)

// result	value	index
// 1 		 2 		 1
// 3 		 3 		 2
// 6 		 4 		 3
// 10 		 5 		 4
// 4
// 15

call_cnt = 0
sum = 0

// 원래는 초기화로 첫 인수지만 초기화 수를 내가 지정하고 싶다면?

console.log("result\tvalue\tindex");
sum = nums.reduce(function (accumulator, item, index, array) {
  console.log(accumulator, "\t\t", item, "\t\t", index);
  call_cnt++;
  return accumulator + item;
},0);
console.log(call_cnt)
console.log(sum)

// result	value	index
// 0 		 1 		 0
// 1 		 2 		 1
// 3 		 3 		 2
// 6 		 4 		 3
// 10 		 5 		 4
// 5
// 15
  • 요소 별 함수 수행 누적 결과값 반환 : Array.reduce(function(accumulator, item, index, array){})
  • accumulator : 이전 함수 결과(initail로 초기값 설정 가능)
  • item : 배열 요소
  • index : 배열 위치
  • array : 배열



나의 회고 🤫

고차함수 내용을 제대로 알지 못해서 항상 코테 문제를 풀 때마다 자신이 없었다.
해당 함수 내용들 완벽하게 숙지하고 이해 못한 부분은 더 공부할 것..!
정렬의 문제점도 이번에서야 제대로 알 수 있었다.
상황에 맞는 함수를 잘 기억해두고 써먹자!!