/ es2015

Iterators ES2015

Javascript Arrayiterable 하다.

let names = ["Flynn", "Hanna", "Dain"];
for(let name of names) {
  console.log(name);
}

Javascript Plain Objectiterable 하지 않다.

let post = {
  title: 'Iterators ES2015',
  comments: 101
};

for(let p of post) {
  console.log(p);
}
// TypeError:post[Symbol.iterator] is not a function

iterableiterator object를 반환한다.
iterator object는 컬렉션에 한번에 하나의 아이템에 접근하는 방법과 순서간의 현재 위치 정보를 알고 있다.

let names = ["Flynn", "Hanna", "Dain"];
for(let name of names) {
  console.log(name);
}

// behind the scenes
let iterator = names[Symbol.iterator]();

let firstRun = iterator.next();
// { done: false, value: 'Flynn' }
let name = firstRun.value;

let secondRun = iterator.next();
// { done: false, value: 'Hanna' }
let name = secondRun.value;

let thirdRun = iterator.next();
// { done: false, value: 'Dain' }
let name = thirdRun.value;

let fourthRun = iterator.next();
// { done: true, value: undefined }

**done(boolean)**은 컬렉션의 리턴할 value가 있는 경우 false
컬렉션이 종료된 경우 true
**value(any)**는 컬렉션의 리턴하는 값 컬렉션 순회가 끝나면 undefined

Iterator Object

let post = {
  title: 'Iterators ES2015',
  comments: 101
};

post[Symbol.iterator] = function() {
  let next = () => {}
  return {next};
}

for(let p of post) {
 console.log(p);
}

// Cannot read property 'done' of undefined
...
post[Symbol.iterator] = function() {
  let properties = Object.keys(this);
  let count = 0;
  let isDone = false;

  let next = () => {
    if(count >= properties.length) {
      isDone = true;
    }
    return { 
      done: isDone,
      value: this[properties[count++]] 
    };
  }
  return {next};
}

for(let p of post) {
  console.log(p);
}

iterable protocol 을 제공하면 spread operator를 사용 할 수 있다.

let values = [...post];
console.log(values); // ['Iterators ES2015', 100]

iterable protocol 을 제공하면 destructuring assignment를 사용 할 수 있다.

let [title, comments] = post;
console.log(title); // Iterators ES2015
console.log(comments); // 100

**Generator**를 사용해서 리팩토링

// Generator function signiture
post[Symbol.iterator] = function *() {
  let properties = Object.keys(this);
  for(let p of properties) {
    yield this[p];
  }
}

// same
post[Symbol.iterator] = function *() {
  yield this.title;
  yield this.comments;
}