Javascript ES6 Iterators建议指南(含实例)

2018-11-13 admin

本文旨在分析理解 Iterators 。 Iterators 是 JavaScript 中的新方法,可以用来循环任意集合。在ES6中登场的Iterators。因其可被广泛使用,并且已在多处场景派上用场,现已十分流行。

我们从概念上去理解iterators,通过实例讲述在何处使用。并且. We’ll also see some of its implementations in JavaScript.

介绍

如果你有下面的数组 ——

const myFavouriteAuthors = [
  'Neal Stephenson',
  'Arthur Clarke',
  'Isaac Asimov', 
  'Robert Heinlein'
];

有时,你需要获取这个数组中每一个值,在屏幕上显示它们,操作它们,或者依据它们做些事情。如果我问你将如何处理?你会说,这很简单——我循环它们就是了,可以用for__, while__, for-of 或者 这些 循环方法中的任意一个。

各种循环数组的方法

如果现在不是前面的数组,而是以自定的数据结构保存所有的authors,比如——

自定数据结构

现在, myFavouriteAuthors 是一个包含了对象 allAuthors 的对象, allAuthors 包含了三个数组,对应key值为 fiction , scienceFiction ,和 fantasy 。 现在如果需要遍历 myFavouriteAuthors 来获取所有的作者, 你的方法是什么? 你可以继续尝试一些循环组合来获取所有数据。

然而,如果你这样做 —

for (let author of myFavouriteAuthors) {   
console.log(author)
}

// TypeError: {} is not iterable</pre>

你会得到一个该对象不是_可迭代的_TypeError。 我们来看看迭代是什么,以及我们如何使对象可迭代。 在本文的最后,你将知道如何在这种情况下,在 myFavouriteAuthors 上,在自定义对象上使用 for-of 循环。

Iterables(可迭代对象) and Iterators(迭代器)

在上一节中看到了问题所在。 没有方法可以简单得从我们的自定义对象中获取所有作者。 我们想要一种方法,通过它我们可以有序地呈现所有内部数据。

让我们在 myFavouriteAuthors 中添加一个返回所有作者的方法 getAllAuthors 。 像这样 ——

getAllAuthors 的实现

这是一个简单的方法。 它完成了获得所有作者的当下目标。 但是,这种实现可能会出现一些问题。 比如——

  • getAllAuthors 这个名字非常具体。 如果其他人正在创建他们自己的 myFavouriteAuthors ,他们可能会将其命名为 retrieveAllAuthors 。
  • 作为开发人员,我们始终需要了解将返回所有数据的特定方法。 在这个案例里,它被命名为 getAllAuthors 。
  • getAllAuthors 返回包含所有作者的字符串数组。 如果另一个开发人员以这种格式返回一个对象数组会怎样——

[ {name: ‘Agatha Christie’}, {name: ‘J. K. Rowling’}, … ]</pre>

开发人员必须知道,返回所有数据的方法的 确切名称和返回类型 。

如果我们制定一个 规则 ,该方法的 名称 及其 返回类型 , 是固定且不可更改的 ,这怎么办?

让我们将这个方法命名为—— **iteratorMethod **.

ECMA 采取了类似的步骤,来标准化循环自定义对象的过程。但是,ECMA使用 Symbol.iterator 而不是 iteratorMethod 。 Symbols 提供唯一且不能与其他属性名称冲突的名称。 此外, Symbol.iterator 将返回一个名为 iterator 的对象。 这个迭代器将有一个名为 next 的方法,它将返回一个包含key为 value 和 done 对象,

key value 中将包含当前值。 它可以是任何类型。 done 是布尔值。 它表示是否已获取所有值。

下图可能有助于建立  iterables  ,  iterators  和  next  之间的关系。 这种关系称为迭代协议。

iterables, iterators, 和 next之间的关系。

参考 Axel Rauschmayer博士 的 Exploring JS 一书 —

  • _ iterable _是一种数据结构,旨在使其元素可在公用环境被访问。 它通过实现一个key为 Symbol.iterator 的方法来实现。 该方法是 **_iterators_的工厂。 也就是说,它将创建 __**iterators **.
  • iterator 是用于遍历数据结构中元素的指针。

使对象可迭代

正如我们在上一节中所学到的,我们需要实现一个名为 Symbol.iterator 的方法。我们将使用 computed property syntax 来设置这个key。举一个简短的例子 —

可迭代的示例

在第4行,我们创建iterator。 这是一个定义了 next 方法的对象。 next 方法根据 step 变量返回对应的值。 在第25行,我们取到 iterator 。 27行,我们调用 next 方法。 接下来我们继续调用,直到 done 变成’true`。

这正是 for-of 循环中发生的事情。 for-of 循环采用 **iterable **,并为其创建  iterator 。 不断调用 next() 直到 done 为真。

JavaScript中的 Iterables

很多东西在JavaScript中都是可迭代的。 它可能不是立等可见的,但如果仔细观察,是能看到iterables的。

这些都是可迭代的 ——

  • Arraysand TypedArrays
  • Strings —迭代每个字符或 Unicode code-points.
  • Maps —迭代 key-value 组合
  • Sets —迭代它们的元素
  • arguments — 函数中一个类似数组的特殊变量
  • DOM 元素 (实现中)

其他在JS中使用iterables的 ——

  • for-of 循环 — for-of 循环需要迭代。 否则,它将抛出一个 TypeError .
for (const value of iterable) { ... }</pre>
  • 数组的解构 ——由于可迭代而发生解构。 我们来看看如何实现。

代码:

const array = ['a', 'b', 'c', 'd', 'e'];
const [first, ,third, ,last] = array;</pre>

相当于

const array = ['a', 'b', 'c', 'd', 'e'];

const iterator = array[Symbol.iterator]();

const first = iterator.next().value
iterator.next().value // Since it was skipped, so it's not assigned
const third = iterator.next().value
iterator.next().value // Since it was skipped, so it's not assigned
const last = iterator.next().value</pre>

代码:

const array = ['a', 'b', 'c', 'd', 'e'];

const newArray = [1, ...array, 2, 3];</pre>

可以写成

const array = ['a', 'b', 'c', 'd', 'e'];

const iterator = array[Symbol.iterator]();

const newArray = [1];
for (let nextValue = iterator.next();nextValue.done !== true;nextValue = iterator.next()) {  
newArray.push(nextValue.value);
}

newArray.push(2)
newArray.push(3)
  • Promise.all 和 Promise.race 接受Promises上的迭代。

Map的构造函数将 [key,value] 形式的迭代器转换为Map,Set的构造函数将可迭代的元素转换为Set——

const map = new Map([[1, 'one'], [2, 'two']]);
map.get(1) 
// one
const set = new Set(['a', 'b', 'c]);
set.has('c');
// true

让myFavouriteAuthors可迭代

这是一个使myFavouriteAuthors可迭代的实现方式。

可迭代的实现示例

根据本文的介绍,您可以轻松了解迭代器的工作方式。 可能有点难以理解它的逻辑,所以,我已经为代码写了注释。 但是,吸收和理解概念的最佳方法是让这些代码在浏览器或node中运行起来。

如有疑问,欢迎回复! 参考:

原文链接:https://www.jianshu.com/p/58b…

[转载]原文链接:https://segmentfault.com/a/1190000017000569

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-45354.html

文章标题:Javascript ES6 Iterators建议指南(含实例)

相关文章
JavaScript常用特效chm下载
下载地址:JavaScript常用特效chm下载 对了,如果打开空白,在手册上右键属性解除锁定即可。 ...
2015-11-12
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
javascript是什么意思
avaScript是Netscape开发的一个对象脚本语言,它使用在世界各地数以百万计的网页和服务器应用程序上。 网景的JavaScript是ecma - 262版的标准脚本语言,和公布的标准只有轻微的差异。 与广为流行的错误理解相反,Ja...
2015-11-12
21天学通javascript
简介: 本书是Javascript入门教程。Javascript是Web开发中应用最早、发展最成熟、用户最多的脚本语言。其语法简洁,代码可读性在众多脚本语言中最好,它在使用时不用考虑数据类型,是真正意义上的动态语言。本书总分为四篇,共21章...
2015-11-16
canvas图片绘制跨域问题解决方案Tainted canvases may not be exported
图片跨域问题的一般解决方法 当使用canvas绘制网络图片的时候,经常会出现“Tainted canvases may not be exported”报错,上网搜一下解决方案,应该给的都是给img添加crossOrigin属性,尝试了一下...
2018-04-19
JavaScript的组成
一个完整的JavaScript由3个部分组成:核心(ECMAScript) 文档对象模型(DOM) 浏览器对象模型(BOM) ECMAScript 描述了该语言的语法和基本对象 ; DOM 描述了处理网页内容的方法和接口 ; BOM 描...
2015-11-12
JavaScript 事件流、事件处理程序及事件对象总结
JS与HTML之间的交互通过事件实现。事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用监听器(或处理程序)来预定事件,以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察员模式,支持页面的行为与页面的外观之间的松散耦合。...
2017-04-05
javaScript+turn.js实现图书翻页效果实例代码
为了实现图书翻页的效果我们在网上可以看到很多教程 在这里推荐turn.js 网上的turn.js 有api 不过是英文的  很多人看起来不方便 .关于代码也是奇形怪状在这里我将详细讲解如何使用turn.js实现翻页效果 ,本篇文章只是讲解 ...
2017-03-16
JavaScript变量的声明
声明变量 变量在脚本中的首次亮相是在其声明中。 在变量首次出现时将会在内存中设置它,因此您稍后可在脚本中引用它。 应在使用变量之前先声明变量。 可以使用 var 关键字实现此目的。 &lt;span id=“mt9” class=“sent...
2015-11-12
jQuery中DOM树操作之使用反向插入方法实例分析
本文实例讲述了jQuery中DOM树操作之使用反向插入方法。分享给大家供大家参考。具体分析如下: 使用反向插入方法 这里我们先把创建的内容插人到元素前面,然后再把同一个元素插人到文档 中的另一个位置。通常,当在jQuery中操作元素时,利用...
2015-11-13
回到顶部