美文网首页
JavaScript中的ES6迭代器

JavaScript中的ES6迭代器

作者: 魂斗驴 | 来源:发表于2021-04-01 09:14 被阅读0次

    我们将在本文中分析Iterators。迭代器是一种遍历JavaScript中任何Set的新方法。它们是在ES6中引入的,并已变得非常流行自从 它们广泛有用,并在各个地方使用。

    我们将在概念上理解什么是迭代器以及在示例中将其使用在何处。我们还将看到它在JavaScript中的一些实现。

    介绍

    假设您有这个数组-

    const myFavouriteAuthors = [
      'Neal Stephenson',
      'Arthur Clarke',
      'Isaac Asimov', 
      'Robert Heinlein'
    ];
    

    在某个时候,您将需要取回数组中的所有单个值,以便在屏幕上打印它们,对其进行操作或对它们执行某些操作。如果我问你,你会怎么做?您会说-这很容易。我就对他们循环中使用forwhilefor-of或一个这些循环的方法。 示例实现为—

    数组上的各种循环技术

    现在,假设您有一个自定义数据结构来容纳所有作者,而不是前面的数组。像这样 -

    自定义数据结构

    现在,myFavouriteAuthors是一个包含另一个object的对象allAuthorsallAuthors包含三个阵列,对应key是fictionscienceFictionfantasy现在,如果我要您遍历myFavouriteAuthors所有作者,您的做法是什么? 您可以继续尝试一些循环组合以获取所有数据。

    但是,如果您这样做-

    for (let author of myFavouriteAuthors) { 
      console.log(author)
    }
    // TypeError: {} is not iterable
    

    你会得到一个TypeError说法,那就是对象是不可迭代的让我们看看什么是可迭代的,以及如何使对象可迭代的。 在本文的最后,您将了解如何for-of在自定义对象(在本例中为on)上使用循环myFavouriteAuthors

    可迭代和迭代器

    您在上一节中看到了问题。没有简单的方法可以从我们的自定义对象中获取所有作者。我们需要一种方法,通过该方法可以顺序公开所有内部数据。

    让我们添加一个方法getAllAuthorsmyFavouriteAuthors返回所有作者。像这样 -

    getAllAuthors实现

    这是一种简单的方法。它完成了我们当前吸引所有作者的任务。但是,此实现可能会出现一些问题。他们之中有一些是 -

    • 这个名字getAllAuthors很具体。如果别人创造了自己的myFavouriteAuthors名字,他们可以给它命名retrieveAllAuthors
    • 作为开发人员,我们始终需要了解将返回所有数据的特定方法。在这种情况下,它名为getAllAuthors
    • getAllAuthors返回所有作者的字符串数组。如果另一个开发人员以这种格式返回对象数组怎么办?
    [ {name: 'Agatha Christie'}, {name: 'J. K. Rowling'}, ... ]
    

    开发人员将必须知道返回所有数据的方法的确切名称和返回类型

    如果我们制定一个规则来确定方法的名称及其返回类型 将是固定且不可更改的,该怎么办?

    我们将此方法命名为– iteratorMethod

    ECMA采取了类似的步骤来标准化循环遍历自定义对象的过程。但是,iteratorMethodECMA使用名称代替了名称Symbol.iteratorSymbols提供的名称是唯一的,并且不能与其他属性名称冲突。同样,Symbol.iterator返回一个称为iterator的对象 。此迭代器将具有称为的方法next,该方法将返回带有键value和的对象done

    value密钥将包含当前值。它可以是任何类型。的done是布尔值。它表示是否已获取所有值。

    图解可以帮助建立关系iterables迭代器,和next这种关系称为迭代协议。

    可迭代,迭代和下一步之间的关系。

    • 一个迭代是想让它的元素向公众开放的数据结构。它是通过实现一个key为Symbol.iterator的方法来实现的。该方法是迭代器的工厂。也就是说,它将创建迭代器
    • 一个迭代器是用于遍历数据结构的元素的指针。

    使objects可迭代

    因此,正如我们在上一节中了解到的那样,我们需要实现一种称为Symbol.iterator的方法。我们将使用计算属性语法来设置此键。一个简短的例子是-

    image.png

    可迭代的例子

    在第4行,我们进行迭代。这是一个已next定义方法的对象。该next方法根据step变量返回值。在第25行,我们检索iterator。我们于27日致电next。我们一直打电话给下一位,直到done成为true

    这正是for-of循环发生的情况。该for-of循环需要一个迭代,并创建它的迭代器。它一直在调用next()直到直到done为真。

    JavaScript中的可迭代

    JavaScript中有很多事情是可迭代的。它可能不会立即可见,但是如果仔细检查,可迭代项将开始显示。

    这些都是可迭代的-

    • 数组TypedArrays
    • 字符串-遍历每个字符或Unicode代码点。
    • Map-遍历其键值对
    • Set-遍历其元素
    • arguments —函数中类似数组的特殊变量
    • DOM元素

    JS中使用可迭代对象的其他一些构造是-

    • for-of循环-在for-of循环需要一个迭代。否则,它将抛出TypeError
    for (const value of iterable) { ... }
    
    • 数组的解构—因为可迭代,所以发生解构。让我们看看如何。

    代码

    const array = ['a', 'b', 'c', 'd', 'e'];
    const [first, ,third, ,last] = array;
    

    相当于

    const array = ['a', 'b', 'c', 'd', 'e'];
    const iterator = array[Symbol.iterator]();
    const first = iterator.next().value
    iterator.next().value // Since it was skipped, so it's not assigned
    const third = iterator.next().value
    iterator.next().value // Since it was skipped, so it's not assigned
    const last = iterator.next().value
    
    • 解构运算符(…)

    代码

    const array = ['a', 'b', 'c', 'd', 'e'];
    const newArray = [1, ...array, 2, 3];
    

    可以写成

    const array = ['a', 'b', 'c', 'd', 'e'];
    const iterator = array[Symbol.iterator]();
    const newArray = [1];
    for (let nextValue = iterator.next(); nextValue.done !== true; nextValue = iterator.next()) {
      newArray.push(nextValue.value);
    }
    newArray.push(2)
    newArray.push(3)
    
    • Promise.allPromise.race在Promises上接受可迭代项。
    • Map和Set

    Map的构造函数将可迭代的over[key, value]对转换为Map,而Set的构造函数将可迭代的over元素转换为Set-

    const map = new Map([[1, 'one'], [2, 'two']]);
    map.get(1) 
    // one
    const set = new Set(['a', 'b', 'c]);
    set.has('c');
    // true
    
    • 迭代器也是了解生成器功能的前提。

    使myFavouriteAuthors可迭代

    这是一个myFavouriteAuthors可迭代的实现。

    const myFavouriteAuthors = {
      allAuthors: {
        fiction: [
          'Agatha Christie', 
          'J. K. Rowling',
          'Dr. Seuss'
        ],
        scienceFiction: [
          'Neal Stephenson',
          'Arthur Clarke',
          'Isaac Asimov', 
          'Robert Heinlein'
        ],
        fantasy: [
          'J. R. R. Tolkien',
          'J. K. Rowling',
          'Terry Pratchett'
        ],
      },
      [Symbol.iterator]() {
        // Get all the authors in an array
        const genres = Object.values(this.allAuthors);
        
        // Store the current genre and author index
        let currentAuthorIndex = 0;
        let currentGenreIndex = 0;
        
        return {
          // Implementation of next()
          next() {
            // authors according to current genre index
            const authors = genres[currentGenreIndex];
            
            // doNotHaveMoreAuthors is true when the authors array is exhausted.
            // That is, all items are consumed.
            const doNothaveMoreAuthors = !(currentAuthorIndex < authors.length);
            if (doNothaveMoreAuthors) {
              // When that happens, we move the genre index to the next genre
              currentGenreIndex++;
              // and reset the author index to 0 again to get new set of authors
              currentAuthorIndex = 0;
            }
            
            // if all genres are over, then we need tell the iterator that we 
            // can not give more values.
            const doNotHaveMoreGenres = !(currentGenreIndex < genres.length);
            if (doNotHaveMoreGenres) {
              // Hence, we return done as true.
              return {
                value: undefined,
                done: true
              };
            }
            
            // if everything is correct, return the author from the 
            // current genre and incerement the currentAuthorindex
            // so next time, the next author can be returned.
            return {
              value: genres[currentGenreIndex][currentAuthorIndex++],
              done: false
            }
          }
        };
      }
    };
    
    for (const author of myFavouriteAuthors) {
      console.log(author);
    }
    
    console.log(...myFavouriteAuthors)
    

    可迭代的示例实现

    利用从本文中获得的知识,您可以轻松地了解迭代器的工作方式。该逻辑可能有点难以遵循。因此,我已经用代码编写了注释。但是,内化和理解该概念的最佳方法是在浏览器或节点中使用代码。

    参考

    A Simple Guide to ES6 Iterators in JavaScript with Examples

    相关文章

      网友评论

          本文标题:JavaScript中的ES6迭代器

          本文链接:https://www.haomeiwen.com/subject/amcthltx.html