함수를 리턴하는 함수이거나 함수를 전달인자로 받는 함수를 말한다.
함수의 전달인자로 전달되는 함수를 콜백함수라고 하고
함수를 리턴하는 함수를 커링함수하고 한다.
function calculate(x, y){
return function(){
return x * y;
}
}
// 함수를 리턴하고 있으므로 고차함수 입니다.
function calcuate(x, y, z){
const plus = function (num1, num2){
return num1 + num2;
}
return plus(x, y) * z
}
// 함수를 전달인자로 받지 않고 있고
// 함수를 리턴하고 있지 않으므로 고차함수가 아닙니다.
1급객체, First Class Object
일급객체란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다.
일급객체의 조건👇
"변수에 할당이 가능하다."
"다른 함수의 전달인자로 전달이 가능하다."
"다른 함수의 결과로서 리턴이 가능하다."
위 조건을 보면 함수를 데이터(string, number, boolean, array, object)
다루듯이 다룰 수 있다는 것을 알 수 있다.
따라서 함수가 일급객체이기에 고차함수로 활용이 가능하다는 것!
배열의 각 요소 특정 논리(함수)에 따르면, 사실(true)일 때 따로 분류한다.
const words = ['elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// ["exuberant", "destruction", "present"]
filter는 이렇게 조건에 맞는 데이터만 분류(filtering) 할 때 사용한다.
const menus = ['americano', 'herb tea', 'earlgrey tea', 'hot choco']
const isTea = function (menu) {
if (menu.includes('tea')) {
return true
}
}
let output = menus.filter(isTea);
console.log(output);
// [ 'herb tea', 'earlgrey tea' ]
배열의 각 요소가 특정 논리(함수)에 의해 다른 요소로 지정된다.
const array1 = [1, 4, 9, 16];
const map1 = array1.map(x => x * 2);
console.log(map1);
// Expected output: Array [2, 8, 18, 32]
map은 이렇게 하나의 데이터를 다른 데이터로 매핑 할 때 사용한다.
// 만화책 모음
const cartoons = [
{
id: 1,
bookType: 'cartoon',
title: '식객',
subtitle: '어머니의 쌀',
createdAt: '2003-09-09',
genre: '요리',
artist: '허영만',
averageScore: 9.66,
},
{
id: 2,
// .. 이하 생략
},
// ... 이하 생략
];
// 만화책 한 권의 부제를 리턴하는 로직(함수)
const findSubtitle = function (cartoon) {
return cartoon.subtitle;
};
// 각 책의 부제 모음
const subtitles = cartoons.map(findSubtitle); // ['어머니의 쌀', ...]
콜백 함수에 두 번째 전달인자를 줄 경우 인덱스를 가져온다.
const arr = [1, 2, 3, 4, 5]
arr.map((el, idx) => `${idx}: ${el * 2}`)
// ['0: 2', '1: 4', '2: 6', '3: 8', '4: 10']
// ❗️참고) 웬만하면 사용하지 않는 것이 좋음
reduce는 이렇게 여러 데이터를, 하나의 데이터로 응축할 때 사용한다.
const sum = [1, 2, 3, 4];
const result = sum.reduce((total, current) => {
return total + current;
}, 0); // 0은 total의 초기값이 0이라는 뜻이다.
console.log(result);
// 10
물론 문자열에서도 사용이 가능하다.
let output = getLongestElement(["one", "two", "three"]);
// 문자열을 요소로 갖는 배열을 입력받아 배열에서 가장 긴 문자열을 리턴
function getLongestElement(arr) {
return arr.reduce((total, current) => {
if (total.length >= current.length) return total;
else return current;
}, "");
}
console.log(output);
// three
forEach는 콜백함수의 배열에 있는 각 요소에 대해 오름차순으로 한 번씩 실행한다.
const array1 = ['a', 'b', 'c'];
array1.forEach(element => console.log(element));
// Expected output: "a"
// Expected output: "b"
// Expected output: "c"
값이 3개라면 2번째는 index, 3번째는 배열 객체를 뜻한다.
arr.forEach(func(value, index, array))
// value : 현재 순회 중인 요소
// index : 현재 순회 중인 요소의 index
// array : 배열 객체
find는 콜백함수의 반환 값이 true인 첫 번째 요소를 반환한다.
const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);
console.log(found);
// 12
findIndex는 콜백함수의 반환 값이 true인 첫 번째 요소의 인덱스를 반환한다.
const array1 = [5, 12, 8, 130, 44];
const isLargeNumber = (element) => element > 13;
console.log(array1.findIndex(isLargeNumber));
// 3
some은 콜백함수의 반환값이 단 한 번이라도 참이면 true,
모두 거짓이라면 false를 반환한다.
const array = [1, 2, 3, 4, 5];
const even = (element) => element % 2 === 0;
console.log(array.some(even));
// true
every는 콜백함수의 반환값이 모두 참이면 true,
하나라도 거짓이면 false를 반환한다.
const isBelowThreshold = (currentValue) => currentValue < 40;
const array1 = [1, 30, 39, 29, 10, 13];
console.log(array1.every(isBelowThreshold));
// true
sort는 요소들을 정렬(유니코드 순서대로)해준다.
const texts = ['aa', 'b', 'd', 'c']
texts.sort()
console.log(texts);
// ['aa', 'b', 'c', 'd']
const array1 = [1, 30, 21, 100000];
array1.sort();
console.log(array1);
// [1, 100000, 21, 30]
// ❗️참고) 숫자는 오름차순으로 정렬되지 않는다.
숫자를 오름차순으로 정리하고 싶다면?
sort() + 비교 함수를 추가해 줘야 한다.
숫자를 오름차순 하기
const nums = [1, 30, 21, 100000];
nums.sort((a, b) => a - b);
console.log(nums);
// [1, 21, 30, 100000]
숫자를 내림차순 하기
const nums = [1, 30, 21, 100000];
nums.sort((a, b) => b - a);
console.log(nums);
// [100000, 30, 21, 1]
data 객체의 allGroup 배열에서 myGroup 배열에 속하지 않는 객체들만 필터링하여 filteredData 배열에 저장하는 코드
const data = {
allGroup: [
{
groupId: 1,
artistId: 1,
groupName: 'BTS',
groupImg: imgs.bts,
grouplogoImg: imgs.btsPng,
},
{
groupId: 2,
artistId: 2,
groupName: 'TXT',
groupImg: imgs.txt,
grouplogoImg: imgs.txtPng,
},
....
.....
myGroup: [
{
groupId: 1,
artistId: 1,
groupName: 'BTS',
groupImg: imgs.bts,
grouplogoImg: imgs.btsPng,
},
{
groupId: 2,
artistId: 2,
groupName: 'TXT',
groupImg: imgs.txt,
grouplogoImg: imgs.txtPng,
},
],
};
// 시간복잡도는 O(n^2)
const filteredData = data.allGroup.filter((group) => {
return !data.myGroup.some((myGroup) => myGroup.groupId === group.groupId);
});
-----
// 위와 같은 결과인 코드
// myGroup 배열의 길이에 상관없이 O(n)의 시간복잡도를 가지는 코드
const myGroupIds = new Set(data.myGroup.map((el) => el.groupId));
const filteredData = data.allGroup.filter((el) => {
// myGroupIds에 현재 group의 groupId가 포함되어 있는지 확인하고
// 포함되어 있지 않은 경우에만 true를 반환합니다.
return !myGroupIds.has(el.groupId);
});
배열의 요소를 특정 기준(key)에 따라 그룹화해 객체로 반환하는 새로운 배열 메서드
const fruits = [
{ name: 'apple', type: 'pome' },
{ name: 'banana', type: "berry' },
{ name: 'cherry', type: 'drupe' },
{ name: 'pear', type: 'pome' },
];
const groupedFruits = fruits.groupBy(fruit = fruit.type);
console.log (groupedFruits);
// {
// pome: [{ name: 'apple', type: 'pome' }, { name: 'pear', type: 'pome' :],
// berry: [{ name: 'banana', type: 'berry' }],
// drupe: [{ name: 'cherry', type: 'drupe' }]
// }
const result = [1, 2, 3, 4, 5].groupBy(x => (x % 2 === 0 ? 'even' : 'odd'));
// { odd: [1, 3, 5], even: [2, 4] }
중복을 허용하지 않는다.
/*
* Set(중복제거) 객체의 주요 메서드
*
* add(value): 새로운 값을 추가합니다.
* delete(value): 주어진 값을 제거합니다.
* has(value): 주어진 값이 존재하는지 확인합니다.
* clear(): 모든 값을 제거합니다.
* size: Set 객체의 요소 개수를 반환합니다.
*
* new Set(array)를 사용하면 중복된 값이 제거된 배열을 반환 함
* const a = new Set([1, 1, 2])
* const b = [...a]
* console.log(b) // [1, 2] 출력 됨.
*/
/* ----- new Set 예시 ----- */
const mySet = new Set(); // Set 객체 생성
// add(value): 새로운 값을 추가합니다.
mySet.add(1);
mySet.add('hello');
mySet.add({ key: 'value' });
console.log(mySet); // Set { 1, 'hello', { key: 'value' } }
// delete(value): 주어진 값을 제거합니다.
mySet.delete('hello');
console.log(mySet); // Set { 1, { key: 'value' } }
// has(value): 주어진 값이 존재하는지 확인합니다.
console.log(mySet.has(1)); // true
console.log(mySet.has('hello')); // false
// clear(): 모든 값을 제거합니다.
mySet.clear();
console.log(mySet); // Set {}
// size: Set 객체의 요소 개수를 반환합니다.
console.log(mySet.size); // 0
key-value 형태의 자료형을 저장 가능하다.
/*
set(key, value): 특정 키에 값을 설정
get(key): 특정 키에 해당하는 값을 반환
has(key): 특정 키가 맵에 존재하는지 여부를 확인
delete(key): 특정 키와 해당하는 값을 맵에서 제거
clear(): 맵의 모든 요소를 제거
size: 맵의 요소 개수를 반환
keys(): 맵의 모든 키를 나타내는 이터레이터를 반환
values(): 맵의 모든 값들을 나타내는 이터레이터를 반환
entries(): 맵의 모든 엔트리(키-값 쌍)를 나타내는 이터레이터를 반환
forEach(callbackFn): 맵의 모든 요소에 대해 주어진 콜백 함수를 실행
*/
/* ----- new Map 예시 ----- */
// Map 객체 생성
const map = new Map();
// set(key, value) 메서드를 사용하여 값 추가
map.set('name', 'tata');
// get(key) 메서드를 사용하여 값 가져오기
console.log(map.get('name')); // tata
// has(key) 메서드를 사용하여 키의 존재 여부 확인
console.log(map.has('name')); // true
// delete(key) 메서드를 사용하여 요소 삭제
map.delete('name');
// size 속성을 사용하여 맵의 요소 개수 확인
console.log(map.size); // 1
// keys() 메서드를 사용하여 모든 키 가져오기
const keys = map.keys();
for (let key of keys) {
console.log(key); // name
}
// values() 메서드를 사용하여 모든 값 가져오기
const values = map.values();
for (let value of values) {
console.log(value); // tata
}
// entries() 메서드를 사용하여 모든 엔트리(키-값 쌍) 가져오기
const entries = map.entries();
for (let [key, value] of entries) {
console.log(`${key}: ${value}`); // name: tata
}
// forEach(callbackFn) 메서드를 사용하여 모든 요소에 대해 콜백 함수 실행
map.forEach((value, key) => {
console.log(`${key}: ${value}`); // name: tata
});
➕ WeakSet, WeakMap도 있음.