반응형
인프런 - 함수형 프로그래밍과 JavaScript ES6+ (inflearn.com)
함수형 프로그래밍과 JavaScript ES6+ - 인프런
ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍,
www.inflearn.com
해당 강의 공부 중...!
맵, 필터, 리듀스
map
const products = [
{name: '반팔티', price: 15000},
{name: '긴팔티', price: 20000},
{name: '핸드폰케이스', price: 15000},
{name: '후드티', price: 30000},
{name: '바지', price: 25000}
];
// 여기서 네임과 프라이스만 뽑아내려면?
함수형 프로그래밍에서는 인자와 리턴값으로 소통하는 것을 권장함
(원래 녀석을 변화시키지 않음.)
const log = console.log;
const map = (f, iter) => {
let res = [];
for (const a of iter) {
res.push(f(a));
}
return res; // iter를 리턴하지 않고 새로운 res를 만들어 리턴함
};
log(map(p => p.name, products)); // 네임 배열
log(map(p => p.price, products)); // 프라이스 배열
- map 함수는 고차함수
- 함수를 값으로 다루면서 원하는 순간에 인자를 적용함
이터러블 프로토콜을 따른 map의 다형성 1,2
- 이터러블 프로토콜을 따르면 다형성이 매우 높음
log([1, 2, 3].map(a => a + 1)); // 가능
log(document.querySelectorAll('*').map(el => el.nodeName)) // 불가능
// 프로토타입에 map 메소드를 구현하지 않았음.
log(map(el => el.nodeName, document.querySelectorAll('*'))); // 위에서 만든 함수는 가능
// 이터레이터 프로토콜을 따르기 때문에 사용 가능
// const it = document.querySelectorAll('*')[Symbol.iterator]();
// log(it.next());
// log(it.next());
// log(it.next());
// log(it.next());
// log(it.next());
function* gen() {
yield 2;
if (false) yield 3;
yield 4;
}
// 이터레이터 프로토콜만 따르면 모두 순회하도록 만들 수 있음
// 많은 헬퍼 함수들과의 조합성이 좋아진다.
log(map(a => a * a, gen()));
- 다른 맵을 살펴보자
- 맵 함수가 아닌 파이썬 딕셔너리와 비슷한 자료형
let m = new Map();
m.set('a', 10);
m.set('b', 20);
const it = m[Symbol.iterator](); // [['a',10],['b',20]]
map(([k, a]) => [k, a * 2], m)) // [['a',20],['b',40]]
log(new Map(map(([k, a]) => [k, a * 2], m))); // 안이 바뀐 맵 객체
filter
- 특정 금액 이상, 이하만 걸러내기
const filter = (f, iter) => {
let res = [];
for (const a of iter) {
if (f(a)) res.push(a);
}
return res;
};
log(...filter(p => p.price < 20000, products)); // {} 가격 20000미만
log(...filter(p => p.price >= 20000, products)); // {} 가격 20000이상
log(filter(n => n % 2, [1, 2, 3, 4])); // [1,3]
log(filter(n => n % 2, function* () {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}()));
// 1,3,5
- 내부 값 다형성은 보조 함수
- 외부 값 다형성은 이터레이터 프로토콜
reduce
- reduce는 iterable 값을 다른 값으로 축약해주는 함수
// 언제 필요할까? const nums = [1, 2, 3, 4, 5]; let total = 0; for (const n of nums) { total = total + n; // 값을 축약 } log(total); // 함수의 조합 const add = (a, b) => a + b; log(add(add(add(add(add(0, 1), 2), 3), 4), 5)); // 함수 , 시작값, 이터러이터 const reduce = (f, acc, iter) => { if (!iter) { // 이터레이터가 아니면 ex 배열 iter = acc[Symbol.iterator](); // 이터레이터 객체를 꺼냄 acc = iter.next().value; // 맨 처음 값을 가져옴 } for (const a of iter) { acc = f(acc, a); } return acc; }; // 보조함수를 통해 축약을 완전히 위임. log( reduce( // iterator 안 객체인 product가 a에 들어가고 total_price가 acc에 들어감 (total_price, product) => total_price + product.price, 0, products));
조합해서 사용해보기
const products = [
{name: '반팔티', price: 15000},
{name: '긴팔티', price: 20000},
{name: '핸드폰케이스', price: 15000},
{name: '후드티', price: 30000},
{name: '바지', price: 25000}
];
const add = (a, b) => a + b;
// filter로 20000원 이하의 제품들을 필터링
// 객체 p 배열을 price 배열로 map
// add함수를 적용해서 reduce (총 가격 계산)
// filter map reduce
log(
reduce(
add,
map(p => p.price,
filter(p => p.price < 20000, products))));
// 20000 이상 filter map reduce
log(
reduce(
add,
filter(n => n >= 20000,
map(p => p.price, products))));
-
함수를 조합해서 평가
-
코드가 계산(Evaluation) 되어 값을 만드는 것
-
맨 처음은 map을 통해 iterator로 뽑아올 값을 평가함
-
그 다음 filter로 조건을 적용한다.
-
reducer로 값을 줄인다.
반응형