1. 1. Iterator遍历器概念
    1. 来源
      1. 集合数组,包括数组,对象,map、set
      2. 相互组合定义自己的结构,为了统一需要一种接口机制来处理所有不同的数据结构
    2. 概念
      1. 它是一种接口,为各种不同的数据结构提供统一的访问机制
      2. 任何对象只要不输遍历器接口,就能执行遍历操作(依次处理所有的对象成员)
    3. 三个作用
      1. a. 提供统一的访问接口
      2. b. 使数据结构的成员依次排列
      3. c. 创造遍历命令for...of循环,即供for...of消费
    4. 四个过程
      1. a. 创建一个指针对象,遍历器本质上是一个指针对象
      2. b. 第一次调用指针的next方法,指向第一个成员
      3. c. 第二次调用next,指向第二个成员
      4. d. 不断调用next,直到结束
      5. 代码模拟
        1. ``` var it = makeIterator(['a', 'b']); it.next() // { value: "a", done: false } it.next() // { value: "b", done: false } it.next() // { value: undefined, done: true } function makeIterator(array) { var nextIndex = 0; return { next: function() { return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {value: undefined, done: true}; } }; } ```
  2. 2. 数据结构的默认Iterator接口
    1. a. Symbol.iterator 只要部署了这个属性默认可遍历
    2. b. 在[symbol.interator]里面部署next方法就能在外界使用next方法,指向下一个值
      1. ``` const obj = { [Symbol.iterator] : function () { return { next: function () { return { value: 1, done: true }; } }; } }; ```
    3. c. 类似于数组对象(存在数值键名和length属性) 可以直接使用数组的Iterator接口
      1. NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; // 或者 NodeList.prototype[Symbol.iterator] = [][Symbol.iterator]; [...document.querySelectorAll('div')] // 可以执行了
      2. 手动实现类数组
        1. let iterable = { 0: 'a', 1: 'b', 2: 'c', length: 3, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; for (let item of iterable) { console.log(item); // 'a', 'b', 'c' }
    4. d. Iterator没有正确实现则报错
      1. var obj = {}; obj[Symbol.iterator] = () => 1; [...obj] // TypeError: [] is not a function
    5. c. 处理用for...of遍历也可用while遍历
  3. 3. 调用Iterator接口的场合
    1. (1)解构赋值
      1. let set = new Set().add('a').add('b').add('c'); let [x,y] = set; // x='a'; y='b' let [first, ...rest] = set; // first='a'; rest=['b','c'];
    2. (2)扩展运算符
      1. // 例一 var str = 'hello'; [...str] // ['h','e','l','l','o'] // 例二 let arr = ['b', 'c']; ['a', ...arr, 'd'] // ['a', 'b', 'c', 'd']
    3. (3)yield*
      1. ``` let generator = function* () { yield 1; yield* [2,3,4]; yield 5; }; var iterator = generator(); a = iterator.next() // { value: 1, done: false } b = iterator.next() // { value: 2, done: false } c = iterator.next() // { value: 3, done: false } d = iterator.next() // { value: 4, done: false } e = iterator.next() // { value: 5, done: false } f = iterator.next() // { value: undefined, done: true } console.log(`${a.value}, ${b.value}, ${c.value}, ${d.value}, ${e.value}`) ```
    4. (4)其他场合
      1. for...of
      2. Array.from()
      3. Map(), Set(), WeakMap(), WeakSet()(比如new Map([['a',1],['b',2]]))
      4. Promise.all()
      5. Promise.race()
  4. 4. 字符串的Iterator接口
    1. 字符串也是类数组对象,也原生具有ITERATOR接口
      1. ``` var someString = "hi"; typeof someString[Symbol.iterator] // "function" var iterator = someString[Symbol.iterator](); iterator.next() // { value: "h", done: false } iterator.next() // { value: "i", done: false } iterator.next() // { value: undefined, done: true } ```
    2. 通过修改Iterator修改方法
      1. var str = new String("hi"); [...str] // ["h", "i"] str[Symbol.iterator] = function() { return { next: function() { if (this._first) { this._first = false; return { value: "bye", done: false }; } else { return { done: true }; } }, _first: true }; }; [...str] // ["bye"] str // "hi"
  5. 5. Iterator接口与Generator函数
    1. Symbol.iterator方法的最简单实现,使用yield
      1. var myIterable = {}; myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; }; [...myIterable] // [1, 2, 3] // 或者采用下面的简洁写法 let obj = { * [Symbol.iterator]() { yield 'hello'; yield 'world'; } }; for (let x of obj) { console.log(x); } // hello // world
  6. 6. 遍历器对象的return(),throw()
    1. 用于抛出错误,或完成
      1. function readLinesSync(file) { return { next() { if (file.isAtEndOfFile()) { file.close(); return { done: true }; } }, return() { file.close(); return { done: true }; }, }; }
    2. readLinesSync ?
  7. 能够进行循环的对象结构
    1. 本质上就是调用这个接口产生的遍历器,可以用下面的代码证明。
      1. const arr = ['red', 'green', 'blue']; let iterator = arr[Symbol.iterator](); for(let v of arr) { console.log(v); // red green blue } for(let v of iterator) { console.log(v); // red green blue }
    2. 数组
      1. let arr = [3, 5, 7]; arr.foo = 'hello'; for (let i in arr) { console.log(i); // "0", "1", "2", "foo" } for (let i of arr) { console.log(i); // "3", "5", "7" }
      2. for..in 与for...of
        1. let arr = [3, 5, 7]; arr.foo = 'hello'; for (let i in arr) { console.log(i); // "0", "1", "2", "foo" } for (let i of arr) { console.log(i); // "3", "5", "7" }
    3. 计算生成的数据结构
      1. entries遍历[key value]
        1. let arr = ['a', 'b', 'c']; for (let pair of arr.entries()) { console.log(pair); } // [0, 'a'] // [1, 'b'] // [2, 'c']
    4. 类似数组的对象
      1. for (let x of 'a\uD83D\uDC0A') { console.log(x); } // 'a' // '\uD83D\uDC0A' 正确识别32位utf-16字符
    5. 对象
    6. Set和Map结构 【name,value】
      1. var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]); for (var e of engines) { console.log(e); } // Gecko // Trident // Webkit var es6 = new Map(); es6.set("edition", 6); es6.set("committee", "TC39"); es6.set("standard", "ECMA-262"); for (var [name, value] of es6) { console.log(name + ": " + value); } // edition: 6 // committee: TC39 // standard: ECMA-262
      2. let map = new Map().set('a', 1).set('b', 2); for (let pair of map) { console.log(pair); } // ['a', 1] // ['b', 2] for (let [key, value] of map) { console.log(key + ' : ' + value); } // a : 1 // b : 2