你知道JavaScript中的可迭代对象与迭代器吗

迭代是访问集合元素的一种方法;可以被迭代的对象称为可迭代对象;迭代器是一个可以记住遍历位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有元素被访问结束,迭代器只能前进不会后退。

Lazy evaluation

Lazy evaluation常被译为“延迟计算”或“惰性计算”,指的是仅仅在真正需要执行的时候才计算表达式的值。

与惰性求值相反的是及早求值(eager evaluation)及早求值,也被称为贪婪求值(greedy evaluation)或严格求值,是多数传统编程语言的求值策略。

充分利用惰性求值的特性带来的好处主要体现在以下两个方面:

避免不必要的计算,带来性能上的提升。

立即学习“Java免费学习笔记(深入)”;

节省空间,使得无限循环的数据结构成为可能。

迭代器

ES6 中的迭代器使惰性求值和创建用户定义的数据序列成为可能。迭代是一种遍历数据的机制。 迭代器是用于遍历数据结构元素(称为Iterable)的指针,用于产生值序列的指针。

迭代器是一个可以被迭代的对象。它抽象了数据容器,使其行为类似于可迭代对象。

迭代器在实例化时不计算每个项目的值,仅在请求时才生成下一个值。 这非常有用,特别是对于大型数据集或无限个元素的序列。

可迭代对象

可迭代对象是希望其元素可被公众访问的数据结构。JS 中的很多对象都是可迭代的,它们可能不是很好的察觉,但是如果仔细检查,就会发现迭代的特征:

new Map([iterable])

new WeakMap([iterable])

new Set([iterable])

new WeakSet([iterable])

Promise.all([iterable])

Promise.race([iterable])

Array.from([iterable])

还有需要一个可迭代的对象,否则,它将抛出一个类型错误,例如:

for … of

… (展开操作符)
const [a, b, ..] = iterable (解构赋值)

yield* (生成器)

JavaScript中已有许多内置的可迭代项:

String,Array,TypedArray,Map,Set。

迭代协议

迭代器和可迭对象遵循迭代协议。

协议是一组接口,并规定了如何使用它们。

迭代器遵循迭代器协议,可迭代遵循可迭代协议。

可迭代的协议

要使对象变得可迭代,它必须实现一个通过Symbol.iterator的迭代器方法,这个方法是迭代器的工厂。

使用 TypeScript,可迭代协议如下所示:

interface Iterable {  [Symbol.iterator]() : Iterator;}

登录后复制

Symbol.iterator]()是无参数函数。 在可迭代对象上调用它,这意味着我们可以通过this来访问可迭代对象,它可以是常规函数或生成器函数。

迭代器协议

迭代器协议定义了产生值序列的标准方法。

为了使对象成为迭代器,它必须实现next()方法。 迭代器可以实现return()方法,我们将在本文后面讨论这个问题。

使用 TypeScript,迭代器协议如下所示:

interface Iterator {    next() : IteratorResult;    return?(value?: any): IteratorResult;}

登录后复制

IteratorResult 的定义如下:

interface IteratorResult {    value?: any;    done: boolean;}

登录后复制

done通知消费者迭代器是否已经被使用,false表示仍有值需要生成,true表示迭代器已经结束。

value 可以是任何 JS 值,它是向消费者展示的值。

当done为true时,可以省略value。

组合

迭代器和可以可迭代对象可以用下面这张图来表示:

bVbOVew.webp.jpg

事例

基础知识介绍完了,接着,我们来配合一些事例来加深我们的映像。

范围迭代器

我们先从一个非常基本的迭代器开始,createRangeIterator迭代器。

我们手动调用it.next()以获得下一个IteratorResult。 最后一次调用返回{done:true},这意味着迭代器现在已被使用,不再产生任何值。

function createRangeIterator(from, to) {  let i = from;  return {    next() {      if (i 

1870223369-5f62da4f3cab5_fix732.png

可迭代范围迭代器

在本文的前面,我已经提到 JS 中的某些语句需要一个可迭代的对象。 因此,我们前面的示例在与for ... of循环一起使用时将不起作用。

但是创建符合迭代器和可迭代协议的对象非常容易。

bVbOVxd.webp.jpg

function createRangeIterator (from, to) {  let i = from  return {    [Symbol.iterator] () {      return this    },    next() {      if (i 

无限序列迭代器

迭代器可以表示无限制大小的序列,因为它们仅在需要时才计算值。

注意不要在无限迭代器上使用扩展运算符(...),JS 将尝试消费迭代器,由于迭代器是无限的,因此它将永远不会结束。 所以你的应用程序将崩溃,因为内存已被耗尽 

同样,for ... of 循环也是一样的情况,所以要确保能退出循环:

function createEvenNumbersIterator () {  let value = 0  return {    [Symbol.iterator] () {      return this    },    next () {      value += 2      return { value, done: false}    }  }}const it = createEvenNumbersIterator()const [a, b, c] = itconsole.log({a, b, c})const [x, y, z] = itconsole.log({ x, y, z })for (const even of it) {  console.log(even)  if (even > 20) {    break  }}

登录后复制

bVbOVz3.webp.jpg

关闭迭代器

前面我们提到过,迭代器可以有选择地使用return()方法。 当迭代器直到最后都没有迭代时使用此方法,并让迭代器进行清理。

for ... of循环可以通过以下方式更早地终止迭代:

break

continue

throw

return

function createCloseableIterator () {  let idx = 0  const data = ['a', 'b', 'c', 'd', 'e']  function cleanup() {    console.log('Performing cleanup')  }  return {    [Symbol.iterator]() { return this },    next () {      if (idx 

bVbOVDp.webp.jpg

登录后复制

如果知道迭代器已经结束,则手动调用cleanup()函数。

如果突然完成,则return()起作用并为我们进行清理。

【推荐学习:javascript高级教程】

以上就是你知道JavaScript中的可迭代对象与迭代器吗的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2709108.html

(0)
上一篇 2025年3月7日 20:28:55
下一篇 2025年2月18日 03:34:55

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • javascript如何删除数组首尾元素?

    上一篇文章中我们了解了给数组添加元素的方法,请看《js如何给数组添加元素》。这次我们来了解一下删除数组首尾元素的方法,有需要的可以参考参考。 之前我们在数组中添加了元素,这次我们想将数组中首尾的元素删除,应该怎么做呢?首先我们来看一下删除数…

    2025年3月7日
    200
  • 解析如何通过javascript来反转数字

    “反转数字”就是逆序输出数字,比如一个数字12345,反转后就是54321;那么在《通过php程序快速将一个正整数反转输出》中我们讲解了如何通过php反转一个数,感兴趣的朋友可以了解一下~ 本文的中心则是讲解如何通过javascript来反…

    2025年3月7日
    200
  • javascript如何删除数组中的任意元素

    上一篇文章中我们了解了删除数组首尾元素的方法,请看《javascript如何删除数组首尾元素?》。这次我们来了解一下删除数组中的任意元素的方法,有需要的可以参考参考。 我们知道了删除数组首尾元素的方法治好,不知道有没有想过如何才能去删除数组…

    2025年3月7日
    200
  • 教你一招判断javascript是否是数组

    上一篇文章中我们了解了删除数组中任意元素的方法,请看《javascript如何删除数组中的任意元素》。这次我们来了解一下判断对象是否是数组的方法,有需要的可以参考参考。 我们知道了如何去创建一个数组对象,如何给数组添加元素,如何删除元素,但…

    2025年3月7日
    200
  • javascript如何颠倒元素位置

    上一篇文章中我们了解了判断对象是否是数组的方法,请看《教你一招判断javascript是否是数组》。这次我们来了解一下颠倒元素位置的方法,有需要的可以参考参考。 我们有时候可以看到正着放进数组里的元素被反着输出了,那你们知道这是怎么回事吗?…

    2025年3月7日
    200
  • 通过js来获取字符串中各个字母出现的次数

    在上一篇文章《解析如何通过javascript来反转数字》中给大家介绍了javascript反转数字的方法,本文继续给大家带来javascript的基础使用,希望对你会有帮助! 正如标题所述,本文的中心问题是“编写一个JavaScript函…

    2025年3月7日
    200
  • javascript如何设置数组长度

    上一篇文章中我们了解了颠倒元素位置的方法,请看《javascript如何颠倒元素位置》。这次我们来了解一下设置数组长度的方法,有需要的可以参考参考。 之前我们知道了不少关于javascript数组的知识了,但是好像没有仔细说过length这…

    2025年3月7日
    200
  • js如何使用join方法把数组中的元素转成字符串

    上一篇文章中我们了解了设置数组长度的方法,请看《javascript如何设置数组长度》。这次我们来了解一下数组元素转变成字符串的方法,有需要的可以参考参考。 我们了解了不少有关于数组的方法,今天我们来介绍一个将数组元素转变成字符串的方法。 …

    2025年3月7日
    200
  • js数组运用之如何使用tostring方法转变成字符串

    上一篇文章中我们了解了使用join方法把数组中元素转成字符串的方法,请看《js如何使用join()方法把数组中的元素转成字符串》。这次我们来了解一下数组元素转变成字符串的另一种方法,有需要的可以参考参考。 上一篇文章介绍了使用join方法把…

    2025年3月7日
    200
  • js数组之间如何进行连接

    上一篇文章中我们了解了数组中元素转成字符串的方法,请看《js数组运用之如何使用tostring方法转变成字符串》。这次我们来了解一下数组之间进行连接的方法,有需要的可以参考参考。 之前我们说过很多js中关于数组对象的方法了,但是我们一直没说…

    2025年3月7日
    200

发表回复

登录后才能评论