千家信息网

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

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,今天就跟大家聊聊有关JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收
千家信息网最后更新 2026年11月02日JavaScript Lazy evaluation中可迭代对象与迭代器是怎样的

今天就跟大家聊聊有关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。

组合

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

事例

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

范围迭代器

我们先从一个非常基本的迭代器开始,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循环一起使用时将不起作用。

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

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   } }

关闭迭代器

前面我们提到过,迭代器可以有选择地使用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); }

  • 如果知道迭代器已经结束,则手动调用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中可迭代对象与迭代器是怎样的有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

迭代 对象 数据 函数 序列 方法 内容 循环 惰性 生成 组合 元素 数据结构 结构 消费 事例 作用 可以通过 意味 手动 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 天津市摩尔互联网科技 广东猪兼强互联网科技有限公司 为想互联网科技怎么样 与互联网科技公司 北京互联网科技公司 腾讯科技 互联网女皇 互联网 新科技 昭通云南众福互联网科技有限公司 河南猎农互联网科技有限公司 知域互联网科技有限公司大骗子 注册互联网科技公司经营范围大全 开一家科技互联网公司需要多少钱 科技类公司包括互联网吗 南通创西澳互联网科技有限公司 互联网科技资金流入 郑州欣桑互联网科技有限公司 2021世界互联网领先科技成果发布 科技互联网专业工作会议发言稿 保山浩联互联网科技有限公司 重庆科技产业互联网有哪些 互联网科技公司排名 江苏根荣互联网科技 云信互联网科技有限公司 科技平台互联网 港股互联网科技股 互联网 科技公司 彤创互联网科技有限公司 洛阳共同富裕互联网科技有限公司 朱啸虎曾投资哪些互联网科技企业 悟空问答互联网科技
0