”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > ES6生成器与迭代器:开发者指南

ES6生成器与迭代器:开发者指南

发布于2025-04-30
浏览:749

ES6 Generators and Iterators: a Developer’s Guide

ES6为JavaScript语言引入了许多新特性。其中两个特性,生成器和迭代器,极大地改变了我们在更复杂的前端代码中编写特定函数的方式。

虽然它们可以很好地协同工作,但它们实际的功能可能有点令人困惑,所以让我们来仔细研究一下。

关键要点

  • ES6提供了一种更简洁的for循环编写方式,提供了一种更类似Python的方式来直接与数据集中的元素交互,使代码更易于阅读和编写。
  • ES6中的生成器是记住每次调用之间状态的函数。它们每次被调用时都可以生成序列中的下一个值,有效地创建自定义迭代。
  • 生成器函数中的“yield”关键字类似于“return”,但它保持函数的状态,允许它在下一次调用时从中断处继续执行。
  • 虽然Node和现代浏览器支持ES6特性,但旧版浏览器可能需要Babel等转译器将ES6代码转换为ECMAScript 5代码。

迭代器

迭代是编程中常见的做法,通常用于循环遍历一组值,转换每个值,或以某种方式使用或保存它以备后用。

在JavaScript中,我们一直都有这样的for循环:

for (var i = 0; i 

但ES6给了我们另一种选择:

for (const i of foo) {
  // 对i执行某些操作
}

这可以说是更简洁、更容易使用,让我想起了Python和Ruby等语言。但是,关于这种新型迭代,还有一点非常重要需要注意:它允许您直接与数据集的元素交互。

假设我们想找出数组中的每个数字是否为素数。我们可以通过创建一个执行此操作的函数来做到这一点。它可能看起来像这样:

function isPrime(number) {
  if (number 

不是世界上最好的,但它有效。下一步是循环遍历我们的数字列表,并使用我们闪亮的新函数检查每个数字是否为素数。这很简单:

var possiblePrimes = [73, 6, 90, 19, 15];
var confirmedPrimes = [];

for (var i = 0; i 

同样,它有效,但它很笨拙,这种笨拙很大程度上取决于JavaScript处理for循环的方式。但是,有了ES6,我们就在新的迭代器中得到了一个几乎类似Python的选项。因此,前面的for循环可以这样编写:

const possiblePrimes = [73, 6, 90, 19, 15];
const confirmedPrimes = [];

for (const i of possiblePrimes){
   if ( isPrime(i) ){
      confirmedPrimes.push(i);
   }
}

// confirmedPrimes现在是[73, 19]

这要干净得多,但最引人注目的是for循环。变量i现在代表名为possiblePrimes的数组中的实际项。因此,我们不再需要按索引调用它了。这意味着我们不必在循环中调用possiblePrimes[i],而只需调用i即可。

在幕后,这种迭代利用了ES6闪亮的新Symbol.iterator()方法。这个方法负责描述迭代,并且在被调用时,返回一个JavaScript对象,其中包含循环中的下一个值和一个done键,该键根据循环是否完成而为true或false。

如果您对这种细节感兴趣,您可以阅读Jake Archibald撰写的这篇精彩博文《Iterators gonna iterate》。当我们深入探讨本文的另一部分:生成器时,它也会让您很好地了解幕后发生了什么。

生成器

生成器(也称为“迭代器工厂”)是一种新型的JavaScript函数,用于创建特定的迭代。它们为您提供了特殊、自定义的循环遍历内容的方式。

好的,那么这一切意味着什么?让我们来看一个例子。假设我们想要一个函数,每次调用它时都会给我们下一个素数:

function* getNextPrime() {
  let nextNumber = 2;

  while (true) {
    if (isPrime(nextNumber)) {
      yield nextNumber;
    }
    nextNumber  ;
  }
}

如果您习惯使用JavaScript,其中一些内容看起来有点像巫术,但实际上它并不太糟糕。我们在关键字function之后有那个奇怪的星号,但这只是告诉JavaScript我们正在定义一个生成器。

另一个奇怪的部分是yield关键字。这实际上是生成器在您调用它时吐出的内容。它大致相当于return,但它保留了函数的状态,而不是在每次调用它时都重新运行所有内容。它在运行时“记住”它的位置,因此下次您调用它时,它会从中断处继续执行。

这意味着我们可以这样做:

const nextPrime = getNextPrime();

然后,每当我们想要获得——你猜对了——下一个素数时,都可以调用nextPrime:

console.log(nextPrime.next().value); // 2
console.log(nextPrime.next().value); // 3
console.log(nextPrime.next().value); // 5
console.log(nextPrime.next().value); // 7

您也可以只调用nextPrime.next(),这在您的生成器不是无限的情况下很有用,因为它返回一个这样的对象:

console.log(nextPrime.next());
// {value: 2, done: false}

在这里,done键告诉您函数是否已完成其任务。在我们的例子中,我们的函数永远不会结束,理论上可以为我们提供所有直到无穷大的素数(如果我们有那么多的计算机内存的话)。

很酷,那么我现在可以使用生成器和迭代器了吗?

尽管ECMAScript 2015已经完成,并且已经存在多年了,但其特性(特别是生成器)的浏览器支持远未完善。如果您真的想使用这些和其他现代特性,您可以查看Babel和Traceur等转译器,它们会将您的ECMAScript 2015代码转换为等效的(如果可能)ECMAScript 5代码。

还有许多在线编辑器支持ECMAScript 2015,或者专门关注它,特别是Facebook的Regenerator和JS Bin。如果您只是想玩玩并了解JavaScript现在如何编写,那么这些值得一看。

结论

生成器和迭代器为我们处理JavaScript问题的方法提供了相当多的新灵活性。迭代器允许我们以更类似Python的方式编写for循环,这意味着我们的代码看起来更简洁,更容易阅读。

生成器函数使我们能够编写记住上次看到它们的位置的函数,并且可以从中断处继续执行。它们在实际记住的内容方面也可以是无限的,这在某些情况下非常方便。

对这些生成器和迭代器的支持很好。它们在Node和所有现代浏览器中都受支持,Internet Explorer除外。如果您需要支持旧版浏览器,最好的办法是使用Babel等转译器。

关于ECMAScript 2015生成器和迭代器的常见问题解答 (FAQ)

ECMAScript 2015中的迭代器和生成器有什么区别?

迭代器和生成器都是ECMAScript 2015的特性,用于处理数据流。迭代器是一个对象,允许程序员遍历集合中的所有元素。它有一个next()方法,返回序列中的下一个项目。另一方面,生成器是一个可以中途停止然后从停止处继续的函数。换句话说,生成器看起来像一个函数,但它的行为像一个迭代器。

如何在ECMAScript 2015中使用yield关键字?

yield关键字用于ECMAScript 2015暂停和恢复生成器函数(function*或旧版生成器函数)。yield可以从生成器函数返回一个值。这个返回值通常是一个具有两个属性的对象:value和done。value属性是计算yield表达式的结果,done是一个布尔值,指示生成器是否已生成其最后一个值。

ECMAScript 2015中next()方法的目的是什么?

next()方法是ECMAScript 2015中迭代器协议的关键部分。它返回一个具有两个属性的对象:value和done。value属性是迭代序列中的下一个值,done是一个布尔值,指示迭代是否完成。如果done为true,则迭代器已超出迭代序列的末尾。

如何在ECMAScript 2015中使用生成器进行异步编程?

ECMAScript 2015中的生成器可用于简化异步编程。它们可用于阻止执行以等待异步操作完成,而不会阻塞整个程序。这可以使异步代码看起来和行为更像同步代码,这更容易理解和推理。

ECMAScript 2015中for…of循环和for…in循环有什么区别?

ECMAScript 2015中的for…of循环用于循环遍历可迭代对象,例如数组、字符串、映射、集合等等。它使用语句调用自定义迭代钩子,这些语句将为每个不同属性的值执行。另一方面,for…in循环用于循环遍历对象的属性。它返回正在迭代的对象的键列表。

如何在ECMAScript 2015中创建自定义迭代器?

在ECMAScript 2015中,您可以通过定义一个具有next()方法的对象来创建自定义迭代器。此方法应返回一个具有两个属性的对象:value和done。value属性是迭代序列中的下一个值,done是一个布尔值,指示迭代是否完成。

Symbol.iterator在ECMAScript 2015中的作用是什么?

Symbol.iterator是ECMAScript 2015中一个特殊的内置符号。它用于指定对象的默认迭代器。当需要迭代一个对象时(例如在for…of循环的开头),它的@@iterator方法将不带任何参数被调用,并且返回的迭代器将用于获取要迭代的值。

你能提供ECMAScript 2015中生成器函数的示例吗?

当然,这是ECMAScript 2015中生成器函数的一个简单示例:

function* idMaker() {
  var index = 0;
  while (true)
    yield index  ;
}
var gen = idMaker(); // "Generator { }"
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

在这个例子中,idMaker函数是一个生成器,它产生一个数字序列。

如何在ECMAScript 2015中使用throw()方法和生成器?

ECMAScript 2015中的throw()方法可用于生成器,以恢复生成器函数的执行并从yield表达式抛出错误。throw()方法可用于处理生成器函数执行期间发生的错误。

done属性在ECMAScript 2015迭代器中的意义是什么?

done属性是一个布尔值,由ECMAScript 2015中的迭代器返回。它指示迭代器是否还有更多值要返回。如果done为true,则迭代器已超出迭代序列的末尾。如果done为false,则迭代器仍然可以生成更多值。

最新教程 更多>
  • 如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    postgresql:为每个唯一标识符提取最后一行,在Postgresql中,您可能需要遇到与在数据库中的每个不同标识相关的信息中提取信息的情况。考虑以下数据:[ 1 2014-02-01 kjkj 在数据集中的每个唯一ID中检索最后一行的信息,您可以在操作员上使用Postgres的有效效率: ...
    编程 发布于2025-07-20
  • Java是否允许多种返回类型:仔细研究通用方法?
    Java是否允许多种返回类型:仔细研究通用方法?
    在Java中的多个返回类型:一种误解类型:在Java编程中揭示,在Java编程中,Peculiar方法签名可能会出现,可能会出现,使开发人员陷入困境,使开发人员陷入困境。 getResult(string s); ,其中foo是自定义类。该方法声明似乎拥有两种返回类型:列表和E。但这确实是如此吗...
    编程 发布于2025-07-20
  • 为什么尽管有效代码,为什么在PHP中捕获输入?
    为什么尽管有效代码,为什么在PHP中捕获输入?
    在php ;?>" method="post">The intention is to capture the input from the text box and display it when the submit button is clicked.但是,输出...
    编程 发布于2025-07-20
  • PHP未来:适应与创新
    PHP未来:适应与创新
    PHP的未来将通过适应新技术趋势和引入创新特性来实现:1)适应云计算、容器化和微服务架构,支持Docker和Kubernetes;2)引入JIT编译器和枚举类型,提升性能和数据处理效率;3)持续优化性能和推广最佳实践。 引言在编程世界中,PHP一直是网页开发的中流砥柱。作为一个从1994年就开始发展...
    编程 发布于2025-07-20
  • 为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    查询模式实现缺失:解决“无法找到”错误在Silverlight应用程序中,尝试使用LINQ建立LINQ连接以错误而实现的数据库”,无法找到查询模式的实现。”当省略LINQ名称空间或查询类型缺少IEnumerable 实现时,通常会发生此错误。 解决问题来验证该类型的质量是至关重要的。在此特定实例中...
    编程 发布于2025-07-20
  • 如何克服PHP的功能重新定义限制?
    如何克服PHP的功能重新定义限制?
    克服PHP的函数重新定义限制 但是,PHP工具腰带中有一个隐藏的宝石:runkit扩展。它使您能够灵活地重新定义函数。 runkit_function_renction_rename() runkit_function_redefine() //重新定义'this'以返回“新和改...
    编程 发布于2025-07-20
  • 如何使用Python有效地以相反顺序读取大型文件?
    如何使用Python有效地以相反顺序读取大型文件?
    在python 反向行读取器生成器 == ord('\ n'): 缓冲区=缓冲区[:-1] 剩余_size- = buf_size lines = buffer.split('\ n'....
    编程 发布于2025-07-20
  • C++20 Consteval函数中模板参数能否依赖于函数参数?
    C++20 Consteval函数中模板参数能否依赖于函数参数?
    [ consteval函数和模板参数依赖于函数参数在C 17中,模板参数不能依赖一个函数参数,因为编译器仍然需要对非contexexpr futcoriations contim at contexpr function进行评估。 compile time。 C 20引入恒定函数,必须在编译时进行...
    编程 发布于2025-07-20
  • 图片在Chrome中为何仍有边框?`border: none;`无效解决方案
    图片在Chrome中为何仍有边框?`border: none;`无效解决方案
    在chrome 中删除一个频繁的问题时,在与Chrome and IE9中的图像一起工作时,遇到了一个频繁的问题。和“边境:无;”在CSS中。要解决此问题,请考虑以下方法: Chrome具有忽略“ border:none; none;”的已知错误,风格。要解决此问题,请使用以下CSS ID块创建带...
    编程 发布于2025-07-20
  • 如何使用node-mysql在单个查询中执行多个SQL语句?
    如何使用node-mysql在单个查询中执行多个SQL语句?
    Multi-Statement Query Support in Node-MySQLIn Node.js, the question arises when executing multiple SQL statements in a single query using the node-mys...
    编程 发布于2025-07-20
  • 如何在JavaScript对象中动态设置键?
    如何在JavaScript对象中动态设置键?
    在尝试为JavaScript对象创建动态键时,如何使用此Syntax jsObj['key' i] = 'example' 1;不工作。正确的方法采用方括号: jsobj ['key''i] ='example'1; 在JavaScript中,数组是一...
    编程 发布于2025-07-20
  • 如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    Red: How to Redirect Multiple User Types to Respective ActivitiesUnderstanding the ProblemIn a Firebase-based voting app with three distinct user type...
    编程 发布于2025-07-20
  • 如何限制动态大小的父元素中元素的滚动范围?
    如何限制动态大小的父元素中元素的滚动范围?
    在交互式接口中实现垂直滚动元素的CSS高度限制问题:考虑一个布局,其中我们具有与用户垂直滚动一起移动的可滚动地图div,同时与固定的固定sidebar保持一致。但是,地图的滚动无限期扩展,超过了视口的高度,阻止用户访问页面页脚。$("#map").css({ marginT...
    编程 发布于2025-07-20
  • 为什么HTML无法打印页码及解决方案
    为什么HTML无法打印页码及解决方案
    无法在html页面上打印页码? @page规则在@Media内部和外部都无济于事。 HTML:Customization:@page { margin: 10%; @top-center { font-family: sans-serif; font-weight: bo...
    编程 发布于2025-07-20
  • 如何在Chrome中居中选择框文本?
    如何在Chrome中居中选择框文本?
    选择框的文本对齐:局部chrome-inly-ly-ly-lyly solument 您可能希望将文本中心集中在选择框中,以获取优化的原因或提高可访问性。但是,在CSS中的选择元素中手动添加一个文本 - 对属性可能无法正常工作。初始尝试 state)</option> < op...
    编程 发布于2025-07-20

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3