广告
返回顶部
首页 > 资讯 > 前端开发 > html >JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的
  • 179
分享到

JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的

2024-04-02 19:04:59 179人浏览 安东尼
摘要

今天就跟大家聊聊有关javascript Lazy evaluation中可迭代对象与迭代器是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。L

今天就跟大家聊聊有关javascript Lazy evaluation中可迭代对象与迭代器是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

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

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

组合

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

JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的

事例

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

范围迭代器

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

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

function createRangeIterator(from, to) {   let i = from;    return {     next() {       if (i <= to) {         return { value: i++, done: false };       } else {         return { done: true };       }     }   } }  const it = createRangeIterator(1, 3);  console.log(it.next()); console.log(it.next()); console.log(it.next()); console.log(it.next());

可迭代范围迭代器

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

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

JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的

function createRangeIterator (from, to) {   let i = from    return {     [Symbol.iterator] () {       return this     },     next() {       if (i <= to) {         return { value: i++, done: false }       } else {         return { done: true }       }     }   } }  const it = createRangeIterator(1, 3)  for (const i of it) {   console.log(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] = it console.log({a, b, c})  const [x, y, z] = it console.log({ x, y, z })  for (const even of it) {   console.log(even)   if (even > 20) {     break   } }

JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的

关闭迭代器

前面我们提到过,迭代器可以有选择地使用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 <= data.length - 1) {         return { value: data[idx++], done: false }       } else {         cleanup()         return { done: true }       }     },     return () {       cleanup()       return { done: true }     }   } }  const it = createCloseableIterator()  for (const value of it) {   console.log(value)   if (value === 'c') {     break   } }  console.log('\n----------\n')  const _it = createCloseableIterator(); for (const value of _it) {   console.log(value); }

JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的

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

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

额外的内容

如果你已经做到了这一点,我们来看看一些额外的内容。

组合器

组合器是将现有可迭代对象组合在一起以创建新可迭代对象的函数。

因此,我们能够创建许多实用函数。那map或者filter呢?看看下面的代码,花一分钟时间来理解它。

function createEvenNumbersIterator() {   let value = 0;    return {     [Symbol.iterator]() {       return this;     },     next() {       value += 2;       return { value, done: false };     }   } }  function map(fn, iterable) {   const iter = iterable[Symbol.iterator]();    return {     [Symbol.iterator]() {       return this;     },     next() {       const n = iter.next();       if (!n.done) {         return { value: fn(n.value), done: false };       } else {         return { done: true };       }     }   } }  function filter(fn, iterable) {   const iter = iterable[Symbol.iterator]();    return {     [Symbol.iterator]() {       return this;     },     next() {       const n = iter.next();       if (!n.done) {         if (fn(n.value)) {           return { value: n.value, done: false };         } else {           return this.next();         }       } else {         return { done: true };       }     }   } }  function take(n, iterable) {   const iter = iterable[Symbol.iterator]();    return {     [Symbol.iterator]() {       return this;     },     next() {       if (n > 0) {         n--;         return iter.next();       } else {         return { done: true };       }     }   } }  function cycle(iterable) {   const iter = iterable[Symbol.iterator]();   const saved = [];   let idx = 0;      return {     [Symbol.iterator]() {       return this;     },     next() {       const n = iter.next();       if (!n.done) {         saved[idx++] = n.value;         return { value: n.value, done: false };       } else {         return { value: saved[idx++ % saved.length], done: false };       }     }   } }  function collect(iterable) {   // consumes the iterator   return Array.from(iterable); }  const evenNumbersIterator = createEvenNumbersIterator(); const result = collect(                 // 7. and collect the result   filter(                               // ⬆️ 6. keep only values higher than 1     val => 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);

看完上述内容,你们对JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网html频道,感谢大家的支持。

--结束END--

本文标题: JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的

本文链接: https://www.lsjlt.com/news/82294.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的
    今天就跟大家聊聊有关JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。L...
    99+
    2022-10-19
  • JavaScript中可迭代对象与迭代器的作用是什么
    今天就跟大家聊聊有关JavaScript中可迭代对象与迭代器的作用是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Lazy evaluation...
    99+
    2022-10-19
  • JavaScript中的迭代器和可迭代对象与生成器
    目录1. 什么是迭代器?1.1 迭代器的基本实现1.2 迭代器的封装实现2. 什么是可迭代对象2.1 原生可迭代对象(JS内置)2.1.1 部分for of 演示2.1.2 查看内置...
    99+
    2022-11-13
  • python中可迭代对象的原理是什么
    这篇文章给大家介绍python中可迭代对象的原理是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。python有哪些常用库python常用的库:1.requesuts;2.scrapy;3.pillow;4.twis...
    99+
    2023-06-14
  • JavaScript详解类数组与可迭代对象的实现原理
    目录可迭代对象(Iterable object)Symbol.iterator把对象本身构造成迭代器String也是可迭代的String的迭代器类数组对象和可迭代对象Array.fr...
    99+
    2022-11-13
  • C# 中使用迭代器等待任务的操作是怎样的
    这篇文章将为大家详细讲解有关C# 中使用迭代器等待任务的操作方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。可能你已经阅读 C#5  关于 async 和&n...
    99+
    2023-06-17
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作