simkkong

[JavaScript] 이터러블 프로토콜을 따른 map의 다형성 본문

Develop/JavaScript

[JavaScript] 이터러블 프로토콜을 따른 map의 다형성

심꽁 2020. 4. 12. 21:25
728x90

인프런의 함수형 프로그래밍과 JavaScript ES6+ 인강의 정리하는 시간을 갖도록 하겠다.

 

먼저 map함수는, 배열인 값에 쓰일 수 있는 함수다.

아래와 같이 배열에 map함수를 적용하여 사용할 수 있다.

// 어레이는 map 함수가 잘 동작.
[1,2,3].map(a => a +1);

map은 ES6문법이 생기게 되면서 좀 더 복잡한 구조를 갖게 되었다. (함수형 자바스크립트, 이터러블:이터레이터)

그러나 document.querySelectorAll처럼, 어레이가 아닌 이터러블 프로토콜을 따르는 구조는 어떨까?
map함수를 찾을 수 없다고 undefined가 나타나게 된다.

//잘못된 예시.
log(document.querySelectorAll('*').map); //undefined

그렇다면 이터러블 프로토콜을 따르는 document.querySelectorAll를 for ...of, 제너레이터 등으로 출력해보자.

// 어떠한 값이든 map함수처럼 결과값을 보내줄 사용자정의 map함수.
const map = (f, iter) => {
	let res = [];
  for (const a of iter) {
    res.push(f(a));
  }
  return res;
};


//querySelectorAll는 어레이를 기반으로 동작하지 않기에, map함수가 존재하지 않는다. querySelectorAll는 이터러블 프로토콜을 따른다.
map(el => el.nodeName, document.querySelectorAll('*')); 
// ["HTML", "HEAD", "META", "TITLE", "META", "META", "META", "META", "SCRIPT", "LINK", "SCRIPT", "STYLE", "BODY", "SCRIPT", "PRE", "BR", "PRE", "PRE", "BR", "PRE"]

// 이터레이터를 통해 next함수로 다음 값들을 꺼낸다.
const it = document.querySelectorAll('*')[Symbol.iterator]();
it.next(); // {value: html, done: false}
it.next(); // {value: head, done: false}
it.next(); // {value: script, done: false}
it.next(); // {value: script, done: false}
it.next(); // {value: body, done: false}

// 제너레이터를 통한 map 사용
function *gen() {
yield 2;
if (false) yield 3;
yield 4;
}
map(a => a * a, gen());

또한 JavaScript에서는 new Map() 을 통해, map으로 값을 만들 수 있다,

let m = new Map();
m.set('a', 10);
m.set('b', 20);

m.get('a'); // 10

또한 map도 심볼이터레이터로 접근할 수 있기에, 이터러블 프로토콜을 이용해서

map을 다시 사용하거나 내용을 변경할 수 있다.

const map = (f, iter) => {
	let res = [];
  for (const a of iter) {
    res.push(f(a));
  }
  return res;
};

let m = new Map();
m.set('a', 10);
m.set('b', 20);

// map의 key와 value값을 비구조화 할당을 통해 접근할 수 있다.
console.log(  map( ([k, v]) => [k, v * 2], m )  );  // [["a", 20], ["b", 40]]

// 만약, map을 통해 만든 값의 내용을 변경하고 싶으면, 구조분해를 통해
// 키 밸류를 구분하여 밸류 값을 변경해서 다시 new Map으로 감싸 새로운 map값으로 만든다.
let m2 = new Map(map (([k, v]) => [k, v * 4], m));
log(m2.get('a')); // 40

 

'Develop > JavaScript' 카테고리의 다른 글

[JavaScript] Currying (커링)  (0) 2022.12.28
[JavaScript] this와 call, apply, bind  (0) 2022.11.29
[JavaScript] 호이스팅이란?  (0) 2020.04.05
Comments