2023.03.05
자바스크립트 스터디 8회차
공부 사이트: https://poiemaweb.com/
29. 배열 고차 함수
고차 함수
- 함수를 인자로 전달받거나 함수를 결과로 반환하는 함수.
- 인자로 받은 함수를 필요한 시점에 호출하거나, 클로저를 생성하여 반환한다.
- 자바스크립트는 고차 함수를 다수 지원하고 있으며, 특히나 Array 객체에서 유용한 고차 함수들을 제공
function makeCounter(predicate){
let num = 0;
return function() { //클로저, num의 상태 유지
num = predicate(num);
return num;
};
}
function increase(n) {
return ++n;
}
function decrease(n){
return --n;
}
const increaser = makeCounter(increase);
console.log(increaser()); //1
console.log(increaser()); //2
const decreaser = makeCounter(decrease);
console.log(decreaser()); //-1
console.log(decreaser()); //-2
1) Array.prototype.sort(compareFunction)
배열의 요소를 적절히 정렬하여 반환한다. 원본 배열 직접 변경
const fruits = ['Melon', 'Banana', 'Orange', 'Apple'];
// 오름차순
fruits.sort();
console.log(fruits);
// 내림차순
fruits.reverse();
console.log(fruits);
// ※ 숫자 정렬 시 주의 ※
const numbers = [6,23,234,10,1,77];
numbers.sort();
console.log(numbers)
그러나 정렬 순서는 문자열 유니코드 순서를 따른다. 그렇기에 배열의 요소가 숫자 타입일 경우 일시적으로 문자열 변환 후 정렬한다.
이는 sort 메소드의 인자로 정렬 순서를 정의하는 비교 함수를 인수로 전달함으로서 해결할 수 있다.
예제 ① 숫자를 요소로 가지는 배열을 정렬
const numbers = [6,23,234,10,1,77];
console.log('원본 ', numbers);
// a-b>0이면 a가 b뒤에, a-b<0이면 a가 b앞에 위치.
numbers.sort((a, b) => a - b);
console.log('오름차순' , numbers);
// b-a>0이면 b가 a 뒤에,b-a<0이면 b가 a앞에 위치
numbers.sort((a, b) => b - a);
console.log('내림차순', numbers);
배열의 요소 순서대로 비교한다기보단, 자바스크립트 내부 로직에 의해 각 요소들을 다 비교하는 듯 하다 (순서 없는 듯)
이해가 잘 안간다면, 크롬 개발자도구 콘솔창에 log 찍어보며 확인해보자.
예제 ② 객체를 요소로 가지는 배열을 정렬
배열에 객체가 저장되어있는 경우에는 함수가 아래와 같이 작성될 수 있다.
const person = [
{name: '홍길동', age: 39},
{name: '고길동', age: 12},
{name: '모박사', age: 22}
];
function compare(key) {
return function(a,b) {
//숫자가 같은 경우 0 반환
return a[key] > b[key] ? 1 : (a[key] < b[key] ? -1 : 0);
};
}
person.sort(compare('name'));
console.log(person);
person.sort(compare('age'));
console.log(person);
코드 이해가 어려워서 log찍어가며 확인해봤다.
const person = [
{name: '홍길동', age: 39},
{name: '고길동', age: 12},
{name: '모박사', age: 22}
];
function compare(key) {
return function(a,b) {
// 숫자가 같은 경우 0 반환
let tmp = a[key] > b[key] ? 1 : (a[key] < b[key] ? -1 : 0);
console.log('a[key]: ',a[key]);
console.log('b[key]: ',b[key]);
console.log(tmp);
return a[key] > b[key] ? 1 : (a[key] < b[key] ? -1 : 0);
};
}
person.sort(compare('name'));
console.log(person);
person.sort(compare('age'));
console.log(person);
2) Array.prototype.forEach(callback, thisArg)
- for문 대신 사용할 수 있는 메소드이다.
- 배열을 순회하며 각 요소에 대해 인자로 주어진 콜백함수를 실행한다. 반환값은 undefined.
- 콜백함수의 매개변수를 통해 배열 요소의 값/인덱스/this를 전달받을 수 있다. (this = forEach메소드 호출한 배열)
- forEach 메소드는 원본 배열을 변경하지 않으나, 콜백함수는 this를 통해 원본 배열을 변경할 수 있다.
- break문 사용 불가능. 모든 배열요소 순회!
- thisArg 인자는 callback 실행 시 this로 사용할 값을 지정할 때 사용한다.
예제 ①
const arr = ['zero','one','two','three'];
let pows = [];
arr.forEach(function(item) {
pows.push(item + 'TEST');
});
console.log(pows);
예제 ②
forEach 메소드는 인수로 전달한 보조 함수를 호출하면서, 3개의 인수를 전달한다.
- item: 배열 요소의 값
- index: 요소 인덱스
- self: this(forEach 메소드를 호출한 배열)
const arr = [1,2,3,4,5];
let total = 0;
arr.forEach(function(item, index, self) {
console.log(`arr[${index}] = ${item}`);
total += item;
});
/**
reduce 메소드를 통해서도 동일한 결과를 얻을 수 있음 .
total = arr.reduce(function(pre,cur){
return pre + cur;
});
**/
console.log('합 :', total);
console.log(arr);
[TIP] 템플릿 리터럴
- ES6부터 새롭게 도입
- 개행, 표현식 삽입이 가능하다.
const name = '홍길동';
console.log(`
안녕하세요. ${name} 입니다.
백틱짱조와요
\\n 안써도된다 얏호
`);
예제 ③ 콜백함수를 통한 원본배열 변경
const arr = [1,2,3,4];
// this를 의미하는 self 인수를 통해 원본 배열 변경
arr.forEach(function(item, index, self){
self[index] = Math.pow(item,2)
});
console.log(arr);
예제 ④ forEach 메소드의 두번째 인자로 this를 전달하는 경우
확실히 예제 ③보다 코드가 길다.
function Square() {
this.array = [];
}
Square.prototype.multiply = function(arr) {
arr.forEach(function(item){
// forEach문에 this를 인수로 전달하지 않으면, 여기서의 this === windows
// 전달했으니 호출한 객체를 가리키겠지
this.array.push(item*item);
},this);
};
/**
화살표 함수를 이용하여 동일 기능 코드 작성
Square.prototype.multiply = function(arr){
arr.forEach(item =>this.array.push(item*item));
};
**/
const square = new Square();
square.multiply([1,2,3,4]);
console.log(square.array);
3) Array.prototype.map(callback, thisArg)
- 배열을 순회하며 각 요소에 대해 인자로 주어진 콜백함수의 반환값으로 새로운 배열을 생성하여 반환한다.
✔ forEech(): 배열을 순회하며 요소 값을 참조하여 특정 행위를 함
✔ map(): 배열을 순회하며 요소 값을 다른 값으로 맵핑
- 콜백함수의 매개변수를 통해 배열 요소의 값/인덱스/this를 전달받을 수 있다. (this = map 메소드를 호출한 배열)
- thisArg 인자는 callback 실행 시 this로 사용할 값을 지정할 때 사용한다.
예제 ①
const arr = [1,2,3];
const roots = arr.map(function(item) {
return Math.sqrt(item);
});
console.log(roots); //새로운 배열 반환
console.log(arr);
예제 ② map 메소드의 두 번째 인자로 this 전달
function Prefixer(prefix){
this.prefix = prefix;
}
Prefixer.prototype.prefixArray = function(arr){
return arr.map(function(x){
// map의 두 번째 인자로 this 미전달 시 this===windows
return this.prefix + x;
}, this);
};
/**
화살표 함수로 동일기능
Prefixer.prototype.prefixArray = function(arr){
return arr.map(x => this.prefix + x);
};
**/
const pre = new Prefixer('TEST_');
const preArr = pre.prefixArray(['홍길동','고길동']);
console.log(preArr);
4) Array.prototype.filter(callback, thisArg)
- 배열을 순회하며 각 요소에 대해 인자로 주어진 콜백함수의 실행 결과가 true인 배열 요소 값만 추출하여 새로운 배열을 반환한다.
- 배열에서 특정 조건을 필터링하여 새로운 배열을 만들고 싶을 때 사용한다. (if문 대체 가능)
- 콜백 함수의 매개변수로 item, index, self를 전달받을 수 있다. (self = this)
- thisArg 인자는 callback 실행 시 this로 사용할 값을 지정할 때 사용한다.
const result = [1,2,3].filter(function (item, index, self) {
// 로그는 모든 요소가 찍음
// 반환값은 홀수만을 반환한다. %는 나머지를 구하는 연산자. 짝수는 나머지가 0임
console.log(`[${index}] = ${item}`);
return item % 2;
});
console.log(result);
5) Array.prototype.reduce(callback, initialValue)
- 배열을 순회하여 각 요소에 대해 이전의 콜백함수 반환값을 전달하여 콜백함수를 실행, 그 결과를 반환한다.
- initialValue 생략 시 배열의 첫 번째 요소를 사용한다.
[콜백함수의 인자] ✔ 순서대로
- accumulator: 반환값 누적 (이전 콜백함수 실행 반환값들을 누적한 값)
- currentValue: 현재 요소
- currentIndex: 현재 요소의 인덱스
- Array: self를 의미. reduce를 호출한 배열
참고로 콜백함수 인자 이름은 무엇으로 해도 상관 없는 듯. 이전 포스팅에는 pre, cur 등으로 사용했었다.
예제 ①
const arr = [1,2,3,4,5];
const sum = arr.reduce(function(previousValue, currentValue, currentIndex, self){
console.log(`[${currentIndex}]`);
console.log(`accumulator: ${previousValue}`);
console.log(`currentValue: ${currentValue}`);
console.log(`Array: ${self}`);
return previousValue + currentValue;
});
console.log(`sum: ${sum}`);
예제 ② 초기값을 전달하는 경우
초기값: 콜백함수에 최초로 전달되는 수
const sum = [1,2,3,4,5].reduce(function(pre,cur){
return pre + cur;
},5);
console.log(sum); //20
예제 ③ 객체의 프로퍼티 값을 합산하는 경우
반드시 초기값을 전달해줄 것.
const products = [
{ id: 1, price: 10 },
{ id: 2, price: 20 },
{ id: 3, price: 30 }
];
const priceSum = products.reduce(function (pre, cur) {
console.log(`pre: ${pre}, cur.price ${cur.price}`);
return pre + cur.price;
},0);
console.log(`priceSum: ${priceSum}`);
※ 초기값을 전달하면 에러를 피할 수 있으므로 언제나 초기값을 전달하는 것이 안전하다.
6) Array.prototype.some(callback,thisArg)
- 배열 내 일부 요소가 콜백 함수의 테스트를 통과하는지 확인하여 그 결과를 true/false로 반환한다.
- 콜백 함수의 매개변수로 item, index, self를 전달받을 수 있다. (self = this)
- thisArg 인자는 callback 실행 시 this로 사용할 값을 지정할 때 사용한다.
let res = [1,2,3,4,5].some(function(item){
return item >4;
});
console.log(res); //true
res = ['apple','melon', 'orange'].some(function(item){
return item === 'orange';
});
console.log(res); //true
7) Array.prototype.every(callback, thisArg)
- 배열 내 모든 요소가 콜백함수의 테스트를 통과하는지 확인하여 그 결과를 true/false로 반환한다.
- 콜백 함수의 매개변수로 item, index, self를 전달받을 수 있다. (self = this)
- thisArg 인자는 callback 실행 시 this로 사용할 값을 지정할 때 사용한다.
const res = [1,2,3,4,5].every(function(item){
return item > 0;
});
console.log(res); //true
8) Array.prototype.find(callback, thisArg)
- 배열을 순회하며 각 요소들에 대해 인자로 주어진 콜백함수를 실행하여 그 결과가 참인 첫번째 요소를 반환한다.
- 없으면 undefined
- 콜백 함수의 매개변수로 item, index, self를 전달받을 수 있다. (self = this)
- 새로운 배열로 반환
const users =[
{id: 1, name: '홍길동'},
{id: 2, name: '고길동'},
{id: 2, name: '홍길빵'}
];
// find 메소드
let res = users.find(function(item){
return item.id ===2;
});
console.log(res);
// filter 메소드
res = users.filter(function(item){
return item.id ===2;
});
console.log(res);
9) Array.prototype.findIndex(callback, thisArg)
- 배열을 순회하여 각 요소에 대해 인자로 주어진 콜백함수를 실행하여 그 결과가 참인 첫 번째 요소의 인덱스를 반환한다.
- 없으면 -1 반환
- 콜백 함수의 매개변수로 item, index, self를 전달받을 수 있다. (self = this)
'프로그래밍 > js' 카테고리의 다른 글
lessons 31. 동기식/비동기식 처리 모델 (0) | 2023.03.03 |
---|---|
lessons 30. DOM (0) | 2023.03.02 |
lessons 27~28. 배열 (0) | 2023.02.28 |
lessons 25~26. 정규표현식, String 객체 (0) | 2023.02.21 |
lessons 22~24. Number, Math, Date 객체 (0) | 2023.02.20 |