자바스크립트는 ES6부터 리스트 순회 방법에 많은 발전이 있다고 한다.
const list = [1, 2, 3];
const str = 'abc';
// ES5에서 순회 방식
for (var i=0; list.length; i++) {
console.log(i);
}
for (var i=0; str.length; i++) {
console.log(i);
}
// ES6에서 순회 방식
for (const a of list) {
console.log(a);
}
for (const a of str) {
console.log(a);
}
ㅇㅅㅇ... 나도 지금까지 ES5 때 for문을 자주 사용하고 있었다.. 물론 forEach, map 등의 함수들도 사용하긴 하지만... ES6 이후의 저 순회 방식을 사용한 기억이 없다.. 좋은 것 배워갑니댜..
이터러블:이터레이터 프로토콜
이터러블/이터레이터 프로토콜은 이터러블을 for...of, 전개 연산자 등과 함께 동작하도록 하는 규약이다.
- 이터러블: 이터레이터를 리턴하는 [Symbol.iterator]()를 가진 값
- 이터레이터: {value, done} 객체를 리턴하는 next()를 가진 값
array와 set, map을 통해 더 자세히 알아봅시다.
Array
const arr = [1, 2, 3];
for (const a of arr) console.log(a);
배열은 키와 값을 가지게 되기 때문에 인덱스를 활용할 수 있다. arr[0]일 때 1, arr[1]일 때 2 처럼
Set
const set = new Set([1, 2, 3]);
for (const a of set) console.log(a);
Set은 배열과 달리 키값이 없다. 즉 인덱스 활용이 불가능하다. set[0]을 입력하면 undefined가 리턴!
즉 배열과는 다른 for문으로 추상화되어 있다.
Map
const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (const a of map.keys()) log(a); // key값만 반환
for (const a of map.values()) log(a); // value값만 반환
for (const a of map.entries()) log(a); // 키, 밸류 반환
for (const a of map) log(a); // 키, 밸류 반환
Symbol은 어떤 객체의 키가 될 수 있다. Symbol.iterator는 객체의 이터레이터를 반환하는 메서드로 for...of에서 사용된다.
let iter1 = arr[Symbol.iterator]();
console.log(iter1.next()); // { value: 1, done: false }
console.log(iter1.next()); // { value: 2, done: false }
console.log(iter1.next()); // { value: 3, done: false }
console.log(iter1.next()); // { value: undefined, done: true }
let iter2 = set[Symbol.iterator]();
console.log(iter2.next()); // { value: 1, done: false }
console.log(iter2.next()); // { value: 2, done: false }
console.log(iter2.next()); // { value: 3, done: false }
console.log(iter2.next()); // { value: undefined, done: true }
ES6 이후부터 순회는 이터러블:이터레이터 프로토콜을 따르기 때문에 매우 중요하다고 한다! 다음은 사용자 정의 이터러블을 통해 더 자세히 알아보자.
const iterable = {
[Symbol.iterator]() {
let i = 3;
return {
next() {
return i == 0 ? {done: true} : {value: i--, done: false};
},
[Symbol.iterator]() { // 이전까지 진행됐던 상테에서 next를 진행할 수 있도록. 이 코드 없으면 TypeError: iterator is not iterable
return this;
}
}
}
};
let iterator = iterable[Symbol.iterator]();
for (const a of iterator) console.log(a);
이터러블:이터레이터 프로토콜에 대해 한 번 더 파보자. 개념적으로 뭔가 더 알고 싶네
MDN docs - Iteration protocols
이터러블 프로토콜(The iterable protocol)
위에서 이터러블은 이터레이터를 리턴하는 [Symbol.iterator]()를 가진 값이라고 정의했었다.
이터러블 프로토콜은 자바스크립트 객체들이 for..of 구조에서의 value들이 loop되는 것과 같은 이터레이션 동작을 정의하거나 사용자 정의하는 것을 허용하는 것이고, 이터러블 하기 위해서는 객체는 @@iterator 메소드를 구현해야 한다. 이것은 객체가 Symbol.iterator key의 속성을 가져야 한다는 것을 의미한다.
Property | Value |
[Symbol.iterator] | object를 반환하는, arguments 없는 function. iterator protocol을 따른다. |
어떠한 객체가 반복되어야 한다면 이 객체의 @@iterator 메소드가 인수없이 호출되고, 반환된 이터레이터는 반복을 통해 획득할 값들을 얻을 때 사용된다.
그럼 이터레이터 프로토콜은 뭐여?
이터레이터 프로토콜(The iterator protocol)
이터레이터 프로토콜은 value들의 sequence를 만드는 표준 방법을 정의한다.
객체가 next() 메소드를 가지고 있고, 아래의 규칙에 따라 구현되었다면 그 객체는 이터레이터다.
Property | Value |
next | 아래 2개의 속성들을 가진 object를 반환하는 arguments가 없는 함수 - done (doneblean) - Iterator(반복자)가 마지막 반복 작업을 마쳤을 경우 true 만약 이터레이터에 return값이 있다면 value의 값으로 지정 - 이터레이터의 작업이 남아있을 경우 false. - value - 이터레이터로부터 반환되는 모든 자바스크립트 값. done이 true일 경우 생략될 수 있음 |
위에서 예시로 들었던 array, set, map 모두 내장 iterable이다.
'개발자 도전기 > [STUDY] JS || TS' 카테고리의 다른 글
JavaScript | FP && ES6+ | go, pipe, curry (0) | 2022.01.27 |
---|---|
JavaScript | FP && ES6+ | map, filter, reduce (0) | 2022.01.25 |
JavaScript | FP && ES6+ | 제너레이터와 이터레이터 (0) | 2022.01.21 |
JavaScript | FP && ES6+ | 함수형 자바스크립트 기본기 (0) | 2022.01.19 |
동기vs비동기, 블로킹vs논블로킹? JS 더 깊게 이해하기(1) (0) | 2021.12.17 |
댓글