본문 바로가기

프로그래밍/js

lessons 29. 배열 고차 함수

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