您当前的位置: 首页 >  Java

@大迁世界

暂无认证

  • 1浏览

    0关注

    739博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

JavaScript Lazy evaluation:可迭代对象与迭代器

@大迁世界 发布时间:2020-11-25 08:19:15 ,浏览量:1

作者:MelkorNemesis 译者:前端小智 来源:medium

点赞再看,养成习惯

本文 GitHub https://github.com/qq449245884/xiaozhi 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料。欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西。

Lazy evaluation

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

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

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

  • 避免不必要的计算,带来性能上的提升。
  • 节省空间,使得无限循环的数据结构成为可能。
迭代器

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 值,它是向消费者展示的值。

donetrue时,可以省略value

组合

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qu7BEdCY-1606263454066)(/img/bVbOVew)]

事例

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

范围迭代器

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

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

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

  return {
    next() {
      if (i  val > 1, map(                // ⬆️ 5. divide obtained values by 2
      val => val / 2, take(             // ⬆️ 4. take only six of them
        6, cycle(                       // ⬆️ 3. make an infinite cycling sequence of them
          take(                         // ⬆️ 2. take just three of them
            3, evenNumbersIterator      // ⬆️ 1. infinite sequence of even numbers
          )
        )
      )
    )
  )
);

console.log(result);

这是一大堆代码,很快我们将看到如何使用生成器和函数式编程概念来重构所有这些内容。保持关注,并注意我的后续文章,我们仍然有很多内容要讲。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。

原文:https://medium.com/@MelrNemesis/javascript-lazy-evaluation-iterables-iterators-e0770a5de96f

交流

文章每周持续更新,可以微信搜索「 大迁世界 」第一时间阅读和催更(比博客早一到两篇哟),本文 GitHub https://github.com/qq449245884/xiaozhi 已经收录,整理了很多我的文档,欢迎Star和完善,大家面试可以参照考点复习,另外关注公众号,后台回复福利,即可看到福利,你懂的。

关注
打赏
1664287990
查看更多评论
立即登录/注册

微信扫码登录

0.0524s