https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Iteration_protocols
Iteration Protocols는 ECMAScript 2015에 나왔으며, 2개의 Protocol을 갖습니다. Iterable protocol과 Iterator protocol입니다.
Iterable 하다라는 것은 하기 조건을 충족했을 때 입니다.
Iterable protocol을 구현한 object는 for…of loop, spread, destructing 등 다양한 곳에서 활용 가능합니다.
Iterator protocol을 준수했다는 것은 해당 객체가 next라는 함수를 가지며, 이 함수는 iterator라는 객체를 Iterator 객체는 done과 value 키를 가진 객체입니다.
string도 빌트인 iterable 객체입니다.
const someString = 'hi';
console.log(typeof someString[Symbol.iterator]); // "function"
const iterator = someString[Symbol.iterator]();
console.log(iterator + ''); // "[object String Iterator]"
console.log(iterator.next()); // { value: "h", done: false }
console.log(iterator.next()); // { value: "i", done: false }
console.log(iterator.next()); // { value: undefined, done: true }
console.log([...someString]); // ["h", "i"]
String, Array, TypedArray, Map, Set은 모두 빌트인 iterable입니다. 즉, [Symbol.Iterator] 키를 갖는 함수를 가지고 있단 뜻이죠.
const myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
console.log([...myIterable]); // [1, 2, 3]
var myObj = {};
new Map([[1,"a"],[2,"b"],[3,"c"]]).get(2); // "b"
new WeakMap([[{},"a"],[myObj,"b"],[{},"c"]]).get(myObj); // "b"
new Set([1, 2, 3]).has(3); // true
new Set("123").has("2"); // true
new WeakSet(function*() {
yield {};
yield myObj;
yield {};
}()).has(myObj); // true
let arr = Array.from(function*(){yield 1; yield 2; yield 3;}());
arr;
// [1, 2, 3]
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 }
function* gen() {
yield ["a", "b", "c"];
}
gen().next(); // {value: Array(1), done: false}
[a, b, c] = new Set(["a", "b", "c"]);
a // "a"
generator object 는 iterator 이면서 iterable 입니다.
var aGeneratorObject = function*(){
yield 1;
yield 2;
yield 3;
}();
typeof aGeneratorObject.next;
// "function", 이것은 next 메서드를 가지고 있기 때문에 iterator입니다.
typeof aGeneratorObject[Symbol.iterator];
// "function", 이것은 @@iterator 메서드를 가지고 있기 때문에 iterable입니다.
aGeneratorObject[Symbol.iterator]() === aGeneratorObject;
// true, 이 Object의 @@iterator 메서드는 자기자신(iterator)을 리턴하는 것으로 보아 잘 정의된 iterable이라고 할 수 있습니다.
[...aGeneratorObject];
// [1, 2, 3]
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
function* idMaker() {
var index = 0;
while (true)
yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
// ...
function* anotherGenerator(i) {
yield i + 1;
yield i + 2;
yield i + 3;
}
function* generator(i) {
yield i;
yield* anotherGenerator(i);
yield i + 10;
}
var gen = generator(10);
console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
const someObj = {
*generator () {
yield 'a';
yield 'b';
}
}
const gen = someObj.generator()
console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: undefined, done: true }
class Foo {
*generator () {
yield 1;
yield 2;
yield 3;
}
}
const f = new Foo ();
const gen = f.generator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
const foo = function* () {
yield 10;
yield 20;
};
const bar = foo();
console.log(bar.next()); // {value: 10, done: false}
function * power(n) {
for(current = n; ; current*=n){
yield current;
}
}
for (let a of power(3)){
console.log(a);
if(a > 32) break;
}