[JS] 8. 고차함수
in JS
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 : 배열
나의 회고 🤫
고차함수 내용을 제대로 알지 못해서 항상 코테 문제를 풀 때마다 자신이 없었다.
해당 함수 내용들 완벽하게 숙지하고 이해 못한 부분은 더 공부할 것..!
정렬의 문제점도 이번에서야 제대로 알 수 있었다.
상황에 맞는 함수를 잘 기억해두고 써먹자!!