ES6-ES11-第一部分-let、const、解构赋值、模板字符串、简化对象写法、箭头函数、函数参数默认值、rest 参数、扩展运算符、Symbol、迭代器、生成器、Promise、Set、Map(四)

简介: ES6-ES11-第一部分-let、const、解构赋值、模板字符串、简化对象写法、箭头函数、函数参数默认值、rest 参数、扩展运算符、Symbol、迭代器、生成器、Promise、Set、Map(四)

11. 迭代器

迭代器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。

  1. ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 使用
  2. 原生具备 iterator 接口的数据(可用 for of 遍历)
    a) Array
    b) Arguments
    c) Set
    d) Map
    e) String
    f) TypedArray
    g) NodeList

Iterator 是对象上的一个属性:Symbol.Iterator

11.1 for of 遍历

const arr = ['apple', 'banana', 'orange']
    // for of 遍历
    console.log('for of 遍历 ---- 获取的是键值')
    for (const iterator of arr) {
      console.log(iterator)
    }
    // for in 遍历
    console.log('for in 遍历 ---- 获取的是键')
    for (const key in arr) {
      console.log(key)
    }
    console.dir(arr)

11.2 工作原理

a) 创建一个指针对象,指向当前数据结构的起始位置

let i = arr[Symbol.iterator]()
    console.log(i)

b) 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员

console.log(i)
    console.log(i.next())

c) 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员

d) 每调用 next 方法返回一个包含 value 和 done 属性的对象

console.log(i)
    console.log(i.next())
    console.log(i.next())
    console.log(i.next())
    console.log(i.next())
    console.log(i.next())

11.3 迭代器应用 – 自定义遍历数据

需要自定义遍历数据的时候,要想到迭代器。

注意:

返回的对象 done 一直为 false 会一直输出,for of 是以返回的对象 done 为 true 为停止条件。

// 声明一个对象
      const obj = {
        name: '对象',
        content: ['属性1', '属性2', '属性3', '属性4'],
        // 1. 先添加iterator接口
        [Symbol.iterator]() {
          // 5. 索引变量
          let index = 0
          // 6. 保存 obj 对象的 this
          const _this = this
          // Result of the Symbol.iterator method is not an object
          // 2. 返回的结果不是一个对象
          return {
            // undefined is not a function
            // 3. 使用 for of 遍历时,会创建一个指针对象,指针对象中有一个next方法
            next() {
              // 7. 判断是否遍历完成
              if (index < _this.content.length) {
                // Iterator result undefined is not an object
                // 4. 需要返回一个对象
                return {
                  value: _this.content[index++],
                  done: false,
                }
              } else {
                return {
                  value: undefined,
                  done: true
                }
              }
            },
          }
        },
      }
      // 使用 for of 遍历
      // 每次返回的结果是 content 的成员
      for (const iterator of obj) {
        console.log(iterator)
      }

12. 生成器

生成器是一个函数。生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

// 生成器函数 function 与函数名中间需要有一个 *,靠左靠右都行
    function * gen() {
      console.log('hello')
    }
    // 生成器函数的执行
    // 直接调用不能运行,需要调用next()方法
    let i = gen()
    console.log(i)
    i.next()

生成器函数相当于一个迭代器对象

12.1 yield 语句

yield 可以看成函数的分割符,把函数分割成若干部分,由 next() 方法控制函数代码的执行。

function * gen() {
      console.log('第1个片段')
      yield 'yield 1'
      console.log('第2个片段')
      yield 'yield 2'
      console.log('第3个片段')
      yield 'yield 3'
      console.log('第4个片段')
    }
    let i = gen()
    i.next() // 执行第1个片段
    i.next() // 执行第2个片段
    i.next() // 执行第3个片段
    i.next() // 执行第4个片段

生成器函数可以使用 for of 遍历:

function * gen() {
      // console.log('第1个片段')
      yield 'yield 1'
      // console.log('第2个片段')
      yield 'yield 2'
      // console.log('第3个片段')
      yield 'yield 3'
      // console.log('第4个片段')
    }
    let i = gen()
    // console.log( i.next() ) // 执行第1个片段
    // console.log( i.next() ) // 执行第2个片段
    // console.log( i.next() ) // 执行第3个片段
    // console.log( i.next() ) // 执行第4个片段
for (const iterator of i) {
      console.log(iterator)
    }

12.2 生成器函数参数传递

function * gen( arg ) {
      console.log(arg)
      let res1 = yield 111
      console.log(res1)
      let res2 = yield 222
      console.log(res1)
      console.log(res2)
      let res3 = yield 333
      console.log(res3)
    }
    // 获取迭代器对象
    let i = gen( 'AAA' )
    console.log(i.next()) // 执行 next 可以获取yield后面的值
    // next参数可以传入实参,实参为yield语句的返回结果
    // 第二个next传入的实参为第一个yield返回的结果
    // 第x个next传入的实参从函数的第x个片段开始可以使用,为上一个yield语句的返回结果
    console.log(i.next('BBB')) 
    console.log(i.next('CCC')) 
    console.log(i.next('DDD')) 

12.3 生成器函数实例 - 1

生成器函数可以用于结果回调地狱。

回调地狱:

// 1s后输出111,2s后输出222,3s后输出333
      setTimeout(() => {
        console.log(111)
        setTimeout(() => {
          console.log(222)
          setTimeout(() => {
            console.log(333)
          }, 3000)
        }, 2000)
      }, 1000)

function f1() {
        setTimeout(() => {
          console.log(111)
          // 继续向下调用
          i.next()
        }, 1000)
      }
      function f2() {
        setTimeout(() => {
          console.log(222)
          i.next()
        }, 2000)
      }
      function f3() {
        setTimeout(() => {
          console.log(333)
          i.next()
        }, 3000)
      }
      // 声明生成器函数
      function * gen() {
        yield f1()
        yield f2()
        yield f3()
      }
      // 迭代器对象
      let i = gen()
      // 调用执行
      i.next()


相关文章
|
3月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
302 1
|
6月前
|
存储 缓存 JavaScript
Set和Map有什么区别?
Set和Map有什么区别?
515 1
|
3月前
|
存储 算法 容器
set_map的实现+set/map加持秒杀高频算法题锻炼算法思维
`set`基于红黑树实现,支持有序存储、自动去重,增删查效率为O(logN)。通过仿函数可自定义排序规则,配合空间配置器灵活管理内存。不支持修改元素值,迭代器失效需注意。`multiset`允许重复元素。常用于去重、排序及查找场景。
|
7月前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
379 121
|
10月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
291 2
|
7月前
|
存储 C++ 容器
unordered_set、unordered_multiset、unordered_map、unordered_multimap的介绍及使用
unordered_set是不按特定顺序存储键值的关联式容器,其允许通过键值快速的索引到对应的元素。在unordered_set中,元素的值同时也是唯一地标识它的key。在内部,unordered_set中的元素没有按照任何特定的顺序排序,为了能在常数范围内找到指定的key,unordered_set将相同哈希值的键值放在相同的桶中。unordered_set容器通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭代方面效率较低。它的迭代器至少是前向迭代器。前向迭代器的特性。
342 0
|
7月前
|
编译器 C++ 容器
用一棵红黑树同时封装出map和set
再完成上面的代码后,我们的底层代码已经完成了,这时候已经是一个底层STL的红黑树了,已经已符合库里面的要求了,这时候我们是需要给他穿上对应的“衣服”,比如穿上set的“衣服”,那么这个穿上set的“衣服”,那么他就符合库里面set的要求了,同样map一样,这时候我们就需要实现set与map了。因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。我们就可以使用仿函数了。
108 0
|
7月前
|
存储 编译器 容器
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
288 0
|
11月前
|
编译器 容器
哈希表模拟封装unordered_map和unordered_set
哈希表模拟封装unordered_map和unordered_set

热门文章

最新文章