for of循环

遍历所有数据结构的统一方式,只要这种数据结构有自己的ierable接口
for…of循环就是调用了被遍历对象的iterator方法得到一个迭代器,从而去遍历内部所有的数据
可以使用break跳出循环

  1. // for...of 循环
  2. const arr = [100, 200, 300, 400]
  3. // for (const item of arr) {
  4. // console.log(item)
  5. // }
  6. // for...of 循环可以替代 数组对象的 forEach 方法
  7. // arr.forEach(item => {
  8. // console.log(item)
  9. // })
  10. // for (const item of arr) {
  11. // console.log(item)
  12. // if (item > 100) {
  13. // break
  14. // }
  15. // }
  16. // forEach 无法跳出循环,必须使用 some 或者 every 方法
  17. // arr.forEach() // 不能跳出循环
  18. // arr.some()
  19. // arr.every()
  20. // 遍历 Set 与遍历数组相同
  21. // const s = new Set(['foo', 'bar'])
  22. // for (const item of s) {
  23. // console.log(item)
  24. // }
  25. // 遍历 Map 可以配合数组结构语法,直接获取键值
  26. // const m = new Map()
  27. // m.set('foo', '123')
  28. // m.set('bar', '345')
  29. // for (const [key, value] of m) {
  30. // console.log(key, value)
  31. // }
  32. // 普通对象不能被直接 for...of 遍历
  33. // const obj = { foo: 123, bar: 456 }
  34. // for (const item of obj) {
  35. // console.log(item)
  36. // }

迭代器Iterator

  1. // 迭代器(Iterator)
  2. const set = new Set(['foo', 'bar', 'baz'])
  3. const iterator = set[Symbol.iterator]()
  4. // console.log(iterator.next())
  5. // console.log(iterator.next())
  6. // console.log(iterator.next())
  7. // console.log(iterator.next())
  8. // console.log(iterator.next())
  9. while (true) {
  10. const current = iterator.next()
  11. if (current.done) {
  12. break // 迭代已经结束了,没必要继续了
  13. }
  14. console.log(current.value)
  15. }

实现可迭代接口Iterable

就是挂载一个iterator方法,然后在方法中实现迭代器对象

  1. // 实现可迭代接口(Iterable)
  2. // const obj = {
  3. // [Symbol.iterator]: function () {
  4. // return {
  5. // next: function () {
  6. // return {
  7. // value: 'zce',
  8. // done: true
  9. // }
  10. // }
  11. // }
  12. // }
  13. // }
  14. const obj = {
  15. store: ['foo', 'bar', 'baz'],
  16. [Symbol.iterator]: function () {
  17. let index = 0
  18. const self = this
  19. return {
  20. next: function () {
  21. const result = {
  22. value: self.store[index],
  23. done: index >= self.store.length
  24. }
  25. index++
  26. return result
  27. }
  28. }
  29. }
  30. }
  31. for (const item of obj) {
  32. console.log('循环体', item)
  33. }

迭代器设计模式

迭代器模式的核心意义:对外提供统一遍历的接口,让外面不需要关心内部的数据结构是怎样的
感受:就像是以前遍历需要使用某种具体的数据结构的独有的遍历方法,例如数组的forEach,而使用该模式,只要在数据结构内部实现可迭代接口,所有数据都只要for of就可以遍历到里面的数据了了

  1. // 迭代器设计模式
  2. // 场景:你我协同开发一个任务清单应用
  3. // 我的代码 ===============================
  4. const todos = {
  5. life: ['吃饭', '睡觉', '打豆豆'],
  6. learn: ['语文', '数学', '外语'],
  7. work: ['喝茶'],
  8. // 提供统一遍历访问接口
  9. each: function (callback) {
  10. const all = [].concat(this.life, this.learn, this.work)
  11. for (const item of all) {
  12. callback(item)
  13. }
  14. },
  15. // 提供迭代器(ES2015 统一遍历访问接口)
  16. [Symbol.iterator]: function () {
  17. const all = [...this.life, ...this.learn, ...this.work]
  18. let index = 0
  19. return {
  20. next: function () {
  21. return {
  22. value: all[index],
  23. done: index++ >= all.length
  24. }
  25. }
  26. }
  27. }
  28. }
  29. // 你的代码 ===============================
  30. // for (const item of todos.life) {
  31. // console.log(item)
  32. // }
  33. // for (const item of todos.learn) {
  34. // console.log(item)
  35. // }
  36. // for (const item of todos.work) {
  37. // console.log(item)
  38. // }
  39. todos.each(function (item) {
  40. console.log(item)
  41. })
  42. console.log('-------------------------------')
  43. for (const item of todos) {
  44. console.log(item)
  45. }