class: center, middle, inverse, title-page # Everything is Iterator ### 2015/06/27 #tng16 ### by @teppeis --- # Hello! * Teppei Sato *
@teppeis
* Cybozu, Inc. / kintone --- class: wdpress background-image: url(wdpress87.jpg) ??? WEB+DB PRESS Vol.87でES6特集を書きました。 --- class: center, middle, inverse # ES6 Iterator --- class: bottom right background-image: url(2arity.png) [http://www.2ality.com/2015/02/es6-iteration.html](http://www.2ality.com/2015/02/es6-iteration.html) ??? Dr. Axelから多くの知見をもらいました。 より詳しく知りたい人は参照してください。 --- # Iterator Pattern > “集約オブジェクトが基にある内部表現を公開せずに、その要素に順にアクセスする方法を提供する。” -- GoF * 集合と反復ロジックの分離 * 反復処理用インターフェイスの統一 * 複数の反復処理を同時に実行可能 --- # Two Core Interfaces ```js interface Iterable { [Symbol.iterator](): Iterator; } interface Iterator { next(): {value: any, done: boolean}; } ``` Symbolを使っているため、既存のオブジェクトを`Iterable`化しても絶対にプロパティが衝突しない。 --- # Array is an Iterable ```js var nums = [1, 2, 3]; var iter = nums[Symbol.iterator](); console.log(iter.next()); // {value: 1, done: false} console.log(iter.next()); // {value: 2, done: false} console.log(iter.next()); // {value: 3, done: false} console.log(iter.next()); // {value: undefined, done: true} ``` --- # for..of consumes an Iterable ```js var nums = [1, 2, 3]; for (let n of nums) { console.log(n); } // 1 // 2 // 3 ``` --- # String is an Iterable ```js var str = "𠮷野家"; var iter = str[Symbol.iterator](); // Surrogate Pair! console.log(iter.next()); // {value: "𠮷", done: false} console.log(iter.next()); // {value: "野", done: false} console.log(iter.next()); // {value: "家", done: false} console.log(iter.next()); // {value: undefined, done: true} ``` --- # for..of consumes String ```js var str = "𠮷野家"; for (let s of str) { console.log(s); } // "𠮷" // "野" // "家" ``` --- # Many other Iterables * Array * String * Map * Set * `entries()`, `keys()` and `values()` * `arguments` * DOM NodeList * Generator --- # Many other consumers * for..of * `Array.from()` * Spread Operator * Destructuring * Map and Set constructors * `Promise.all()`, `Promise.race()` * `yield*` --- name: chart background-image: url(iterator.png) # Iterable as a Hub .footnote.right[Inspired by Dr. Axel] --- background-image: url(iterator-map-forof.png) # Map and for..of --- # Map and for..of ```js var map = new Map(); map.set('k1', 'v1'); map.set('k2', 'v2'); for (let [k, v] of map) { console.log(`key: ${k}, value: ${v}`); } // "key: k1, value: v1" // "key: k2, value: v2" ``` --- background-image: url(iterator-string-spread.png) # String and Spread Operator --- # String and Spread Operator `strlen` function for surrogate pairs ```js function strlen(str) { return [...str].length; } strlen("𠮷野家"); // 3 ``` --- background-image: url(iterator-nodelist-destructuring.png) # NodeList and Destructuring --- # NodeList and Destructuring ```js var [first, second] = document.querySelectorAll('.foo .bar'); ``` --- template: chart --- class: center, middle, inverse # Warning --- # Object is not iterable JSのObjectはすべてのオブジェクトの基底クラスなので、デフォルトでIterableにするといろいろ大変なことになる。 特定のオブジェクトをIterableにするのは自由。 --- class: center, middle, inverse # Conclusion --- # Before ES6 Iterator * for loop * ArrayLike、インデックスに頼る or 自前走査 * for..in loop * オブジェクトプロパティの曖昧さ、順不定 * Array#forEach * Arrayを継承 or メソッドの実装が必要 --- # After ES6 Iterator * `Symbol.iterator`を使うのでどんなオブジェクトをIterableにしてもコンフリクトしない * Iteratorの実装が分離されてるので元のオブジェクトが汚れない * IterableもConsumerも自由に実装して組み合わせられる --- class: center, middle, inverse # Thanks!