首页前端开发JavaScript你知道JavaScript中的可迭代对象与迭代器吗

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

时间2024-01-30 03:52:03发布访客分类JavaScript浏览779
导读:收集整理的这篇文章主要介绍了你知道JavaScript中的可迭代对象与迭代器吗,觉得挺不错的,现在分享给大家,也给大家做个参考。迭代是访问集合元素的一种方法;可以被迭代的对象称为可迭代对象;迭代器是一个可以记住遍历位置的对象,迭代器对象从集...
收集整理的这篇文章主要介绍了你知道JavaScript中的可迭代对象与迭代器吗,觉得挺不错的,现在分享给大家,也给大家做个参考。迭代是访问集合元素的一种方法;可以被迭代的对象称为可迭代对象;迭代器是一个可以记住遍历位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有元素被访问结束,迭代器只能前进不会后退。

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

关闭迭代器

前面我们提到过,迭代器可以有选择地使用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()起作用并为我们进行清理。

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

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

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

javascript前端

若转载请注明出处: 你知道JavaScript中的可迭代对象与迭代器吗
本文地址: https://pptw.com/jishu/592004.html
Node.js项目中如何安装和使用ESLint 编写一个JavaScript程序来列出JavaScript对象的属性

游客 回复需填写必要信息