똑같은 삽질은 2번 하지 말자
Javascript ES6+ 에서 함수형 프로그래밍(리스트 순회, Iterable Iterator 프로토콜 ) 본문
기존과 달라진 ES6에서의 리스트 순회
for i++ -> for of
const list = [1, 2, 3];
for (var i = 0; i < list.length; i++) {
console.log(list[i]);
}
const str = 'abc';
for (var i = 0; i < str.length; i++) {
console.log(str[i]);
}
// ES6 +
for (const a of list) {
console.log(a);
}
for (const a of str) {
console.log(a);
}
- 상당히 간결하게 바뀌었다.
- 어떻게 리스트를 순회할까 명령적인 방식에서 선언적으로 바뀌었다
그냥 간결하게 바뀌었다는 것, 이상의 의미가 있는데 ES6이 개발자들에게 어떠한 규약을 제시해 주었고 어떻게 순회에 대해서
추상화를 했고, 어떻게 사용하도록 했는지 ? 에 대해서 알아보자
Iterable & Iterator
for .. of.. 은 어떻게 순회를 하고 있을까?
우선 일반적인 index를 이용한 접근이 아니라는것을 이하의 코드로 알 수 있다.
<script>
log('Set -----------');
const set = new Set([1, 2, 3]);
for (const a of set) log(a); // 1 2 3 출력
</script>
for of 문을 이용하면 내부의 요소들에 하나하나 접근해서 출력을 해주고 있지만.
위의 사진처럼 보통의 for문 처럼 index로는 접근이 불가능하다.
그럼 어떻게 ? Symbol.iterator 를 이용한 것이다.
Symbol.iterator란 무엇인가? 어떻게 이걸 이용하는가?
그걸 알기 위해선 Iterable/Iterator 프로토콜 이란 무엇인지를 알아야한다.
Iterable/Iterator 프로토콜
- Iterable: Iterator 리턴하는 [Symbol.iterator]() 를 가진 값 -> Array, Set, Map등은 Iterable이다.
- Iterator: { value, done } 객체를 리턴하는 next() 를 가진 값
- Iterable/Iterator 프로토콜: Iterable을 for...of, 전개 연산자 등과 함께 동작하도록한 규약
위의 프로토콜에 의해 for..of, 전개 연산자를 통한 Iterable(Array, Set, Map...) 들의 순회가 가능한 것이다.
let iterator = set[Symbol.iterator]();
iterator.next(); // 1
iterator.next(); // 2
iterator.next(); // 3
그럼 iterable을 어떻게 구현할 수 있을까?
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next() { // value, done을 리턴하는 next()
return i == 0 ? {done: true} : {value: i--, done: false};
},
[Symbol.iterator]() { // 자기자신 Symbol.iterator를 리턴하는 [Symbol.iterator]()
return this;
}
}
}
};
이터러블은 Symbol.iterator를 가지고 있고 Symbol.iterator을 실행하면 자기자신을 return한다.
const iter = arr[Symbol.iterator]() // 이터레이터
const iter2 = iter[Symbol.iterator]() // 이것도 이터레이터
이렇게 된 이터러블이 Well-formed Iterable이라고 불리어진다.
그럼 iterable/iterator들은 어디에서 쓸수있나?
javascript에서 내장된 친구들(Array, Map, Set...) 만 이 프로토콜을 따르는게 아니라 오픈 라이브러리에서 순회가능한 친구라 하면
대부분 iterable/iterator프로토콜을 따르고있다. 그리고 Web APIs에 있는 dom과 관련된 친구들도 이 프로토콜을 따르고있다.
참고로 전개 연산자(... ) 도 이 프로토콜을 따르고있다.
const a = [1, 2];
// a[Symbol.iterator] = null;
console.log(...a); // 위의 iterable을 null로 한다면 iterable이 아니다 라는 에러가 발생
*참고
https://gist.github.com/qodot/ecf8d90ce291196817f8cf6117036997
'Javascript' 카테고리의 다른 글
Javascript ES6+ 에서 함수형 프로그래밍(go, pipe,curry) (0) | 2021.08.26 |
---|---|
Javascript ES6+ 에서 함수형 프로그래밍(제너레이터) (0) | 2021.08.21 |
Javascript ES6+ 에서 함수형 프로그래밍(평가, 일급, 일차함수, 고차함수) (0) | 2021.08.16 |
Promise.all() 여러개의 비동기함수를 실행 (0) | 2021.08.04 |
내가 원하는 노드(태그)로 자동 스크롤 하는 방법 (0) | 2021.07.19 |