반복가능한 객체 iterable과 그 속성인 iterator
이터러블은 반복이 가능한 객체를 뜻하며 이는
for..of혹은 그와 같은 방식에서 사용 가능함을 의미한다.
- 이터러블은
@@iterator메서드를 가지며for..of는@@iterator메서드를 호출해 객체를 반복한다. 즉, 객체 자신이나 프로토파입 체인(prototype chain)의 객체중 하나가[Symbol.iterator]key의 속성을 가져야 한다.
내장 iterables : String, Array, TyprArray 이 객체들의 프로토타입 객체들은 모두 @@iterator 메서드를 가지고 있다.
let str = 'abcdef';
typeof str[Symbol.iterator]; // 'function'
let arr = [1, 2, 3];
typeof arr[Symbol.iterator]; // 'function'
for(const word of str) {console.log(word)}
// 'a'
// 'b'
// 'c'
// 'd'
// 'e'
// 'f'
for(const el of arr) {console.log(el)}
// 1
// 2
// 3
iterable을 허용하는 API : Map([iterator]), WeakMap([iterator]), Set([iterator]), WeakSet([iterator]), Promise.all(iterator), Promise.race(iterator), Array.from()
var myObj = {};
let map = new Map([[1,"a"],[2,"b"],[3,"c"]]).get(2); // "b"
typeof map[Symbol.iterator]; // 'function'
let weakMap = new WeakMap([[{},"a"],[myObj,"b"],[{},"c"]]).get(myObj); // "b"
typeof weakMap[Symbol.iterator]; // 'function'
let set = new Set([1, 2, 3]).has(3); // true
typeof set[Symbol.iterator]; // 'function'
let weakSet = new Set("123").has("2"); // true
typeof weakSet[Symbol.iterator]; // 'function'
let weakSet2 = new WeakSet(function*() {
yield {};
yield myObj;
yield {};
}()).has(myObj); // true
typeof weakSet2[Symbol.iterator]; // 'function'
iterable과 함께 사용되는 문법 : for..of, spread operator, yield*, destructuring assignment
for(let value of ["a", "b", "c"]){
console.log(value);
}
// "a"
// "b"
// "c"
[..."abc"]; // ["a", "b", "c"]
function* gen(){
yield* ["a", "b", "c"];
}
gen().next(); // { value:"a", done:false }
[a, b, c] = new Set(["a", "b", "c"]);
a // "a"
next()메서드를 가지는 객체
next() : 아래의 속성들을 가진 object를 반환하는 arguments가 없는 함수
done (boolean)true. 만약 iterator에 return값이 있다면 value의 값으로 지정false. iterator에 done 값을 지정하지 않는 것과 같다.value : iterator로부터 반환되는 모든 자바스크립트 값, done이 true일 경우 생략 가능 Symbol.iterator : object를 반환하는 arguments가 없는 함수, the iterator peotocol 에 따라 구현
let numObj = {
from: 1,
to: 5
};
// for..of 최초 호출 시, Symbol.iterator가 호출
numObj[Symbol.iterator] = function() {
// Symbol.iterator는 이터레이터 객체를 반환
// 이후 for..of는 반환된 이터레이터 객체만을 대상으로 동작, 이때 다음 값도 정해진다.
return {
current: this.from,
last: this.to,
// for..of 반복문에 의해 반복마다 next()가 호출
next() {
// next()는 값을 객체 {done:.., value :...}형태로 반환
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
};
for (let num of numObj) {
alert(num); // 1, then 2, 3, 4, 5
}
반복 가능하고 배열 자체가 아니라는 점에서 유사하지만 구조적으로 차이를 가진다.
이터러블(iterable) : Symbol.iterator 즉 @@iterator 메서드가 구현된 객체
유사 배열(Array-like) : index와 length 프로퍼티가 있어 배열처럼 보이는 객체
둘은 for..of 혹은 그와 같은 방식에서 사용할 수 있는지 여부가 다르다. 유사배열은 for..of 를 사용할 수 없다.
이터러블엔 메서드 @@iterator(Symbol.iterator)가 구현되어 있어야 한다.
obj[Symbol.iterator]의 결과를 이터레이터라고 부르며, 이터레이터는 이어지는 반복 과정을 처리한다.{done: Boolean, value: any}을 반환하는 메서드 next()가 구현되어 있어야 한다.메서드 Symbol.iterator는 for..of에 의해 자동으로 호출된다. 개발자가 명시적으로 호출하는 것도 가능하다.
문자열이나 배열 같은 내장 이터러블에도 Symbol.iterato가 구현되어 있다.
인덱스와 length 프로퍼티가 있는 객체는 유사 배열이라 불린다. 유사 배열 객체엔 다양한 프로퍼티와 메서드가 있을 수 있지만 배열 내장 메서드의 경우에는 없다.
참고 사이트