Map 메서드
const products = [
{ name: '허니버터칩', price: 1500 },
{ name: '벌집핏자', price: 1800 },
{ name: '치킨팝', price: 800 },
{ name: '에낙', price: 500 },
];
위와 같은 배열이 있다고 할 때, 이 배열 속 요소들의 객체에서 name만 뽑아낼 수 있는 방법은 간단하게 두 가지가 있다.
const names = [];
for (const product of products) {
names.push(product.name);
}
이와 같이 순회를 하면서, 각 객체 안에 접근하여 name들을 새로운 빈 배열에 push하면서 증가시키는 방식이다.
이를 함수형 프로그래밍으로 풀어서 접근하면 아래와 같이 작성할 수 있다.
const map = (iter) => {
const res = [];
for (const p of iter) {
res.push(p.name);
}
return res;
};
이때, iterable한 객체에서 어느 값을 가져올 지 함수 자체를 받아서 처리할 수 있다.
const map = (f, iter) => {
const res = [];
for (const p of iter) {
res.push(f(p));
}
return res;
};
이렇게 하면 원하는 시점에 인자를 받아, 원하는 대로 가공하여 새로운 배열을 만들어 낼 수 있는 것이다.
map의 다형성
자바스크립트에서 querySelectAll()의 반환값을 매핑하여 새로운 배열을 만들고자 한다고 가정해보겠다.
document.querySelectAll('*').map(el => el.nodeName);
하지만, 이때의 결과는 undefined가 된다.
그런데 보통의 Array는 map 메서드를 자유롭게 사용할 수 있다.
[1, 2, 3].map(a => a + 1);
// [2, 3, 4]
이때, Array는 제대로 새로운 배열이 만들어지게 되는데, 그렇기 때문에 querySelectAll의 반환값은 map 함수가 내장되어 있지 않다. 실제로 Prototype에서 map 함수를 가지고 있지 않았다.
이를 앞서 만들었던 map 함수에 인자로 넣으면 아래와 같이 나타난다.
map(el => el.nodeName, document.querySelectAll('*'));
// ["HTML", "HEAD", "SCRIPT", "SCRIPT", "BODY", "SCRIPT", "SCRIPT"];
map안에서는 for of 문을 사용했었는데, 이때 결과가 정상적으로 반환된 것을 보면 document.querySelectAll() 함수의 반환 값이 이터러블한 객체임을 알 수 있다.
즉, 제너레이터 함수를 통해서 순회에 진행할 이터러블 객체를 우리의 사용자 정의 map 함수의 인자로 사용할 수 있게 된다.
function *gen() {
yield 2;
yield 3;
yield 4;
}
map(a => a * a, gen());
// [4, 9, 16]
이는 우리의 map 함수가 다형성이 높은 것을 보여준다.
함수형 프로그래밍에 대해서 잘 모르고 있어서 앞에서의 강의가 나에게 어떤 인사이트가 될지 궁금했었다. 그런데 이번에 수강한 강의는 함수형 프로그래밍에 대한 대략적인 개요를 느낄 수 있었다. 먼저, map 함수를 사용자 정의로 새로 만들어 보면서 조금 더 포괄적으로 적용할 수 있는 함수를 만들었다. querySelectAll이 map 정적 메서드를 사용할 수 없어서 다형성이 좋지 않았지만, map 사용자 정의함수는 인자로 값을 변환하는 함수 포인터와 이터러블 프로토콜을 따르는 값을 집어 넣어 조금 더 다형성이 좋은 함수를 만들었다.
이러한 부분이 자바스크립트로 구현할 수 있는 함수형 프로그래밍이라는 걸 알 수 있어서 생각의 조금 확장시킬 수 있는 기회였다.
출처: https://www.inflearn.com/course/functional-es6/dashboard
'프론트엔드 > JS' 카테고리의 다른 글
[JavaScript] Map + Filter + Reduce 중첩 사용과 함수형 사고 (0) | 2023.04.27 |
---|---|
[JavaScript] 이터러블 프로토콜과 map, filter, reduce (2) | 2023.04.25 |
[JavaScript] ES6에서의 순회와 이터러블 (2) | 2023.04.22 |
[JavaScript] Number, Math (0) | 2022.09.27 |
[JavaScript] Symbol (0) | 2022.09.27 |