迭代器由任意对象实现的接口,支持连续获取对象产出的每个值; 默认Symbol.iterator 属性。

消费方式:

  • 手动调用next()方法消费
  • for…of 循环自动消费(for( ; ; )、forEach)

迭代器模式, 可以支持迭代消费的数据结构(可迭代对象)

  1. '12345'
  2. [1, 2, 3, 4, 5]
  3. new Map().set('a', 1).set('b', 2)
  4. new Set().add(1).add(2).add(3)
  5. arguments对象
  6. NodeListDOM集合类型

原生语言:for…of、数组结构、扩展操作符、Array.from()、创建集合、创建映射、Promise.all()、Promise.race()、yield*

  1. let iter = [1, 2, 3, 4][Symbol.iterator]();
  2. iter.next() // {done: false, value: 1}, 最后{value: undefined, done: true}

自定义迭代器

  1. class Counter {
  2. constructor(limit) {
  3. this.limit = limit
  4. }
  5. [Symbol.iterator]() {
  6. let count = 1, limit = this.limit;
  7. return {
  8. next () {
  9. if (count <= limit) {
  10. return { done: false, value: count++ };
  11. } else {
  12. return { done: true, value: undefined };
  13. }
  14. }
  15. }
  16. }
  17. }

考察点:

  1. 给出打印结果并说明原因
    1. let arr = [1,2,3]
    2. arr.name = 'Jack'
    3. arr.length // 3
    4. console.log(Object.keys(arr)) // ["0", "1", "2", "name"]
    5. for(let i in arr) { console.log('in', i) } // 0, 1, 2, 3, name
    6. for (let i of arr) { console.log(i) } // 1, 2, 3
  • for…in 是枚举全部属性
  • for…of 是迭代器
  1. 改造数据使得for…of可遍历出全部值

解决方法1:

  1. let arr = [1,2,3]
  2. arr.name = 'Jack'
  3. // Symbol.iterator
  4. arr[Symbol.iterator] = function () {
  5. let index = 0;
  6. const _this = this;
  7. const keys = Object.keys(_this);
  8. const len = keys.length;
  9. return {
  10. next() {
  11. if (index < len) {
  12. return {
  13. value: _this[keys[index++]],
  14. done: false
  15. }
  16. }
  17. return {
  18. value: null,
  19. done: true
  20. }
  21. }
  22. }
  23. }
  24. let iter = arr[Symbol.iterator]()
  25. for (let i of arr) {
  26. console.log(i)
  27. }
  28. // 1
  29. // 2
  30. // 3
  31. // Jack

方式2: 生成器函数

  1. let arr = [1,2,3]
  2. arr.name = 'Jack'
  3. // Symbol.iterator
  4. arr[Symbol.iterator] = function* () {
  5. const keys = Object.keys(this);
  6. for (let i = 0; i < keys.length; i++) {
  7. yield this[keys[i]]
  8. }
  9. }
  10. let iter = arr[Symbol.iterator]()
  11. for (let i of arr) {
  12. console.log(i)
  13. }
  14. // 1
  15. // 2
  16. // 3
  17. // Jack

https://gitee.com/daaasheng/my_code_block/commit/b589b41274619c291a7b711ddada1fb72bd65a0e

疑问:

  1. for (let item of arr ) {iter.next()} 与 for(let item of iter) 区别?
  2. 提前终止, 出发迭代器是否重新开始