ES6 中引入了很多此前没有但是却非常重要的概念,Iterator就是其中一个。Iterator对象是一个指针对象,实现类似于单项链表的数据结构,通过next()将指针指向下一个节点 ———— 这里也就是先简单做一个概念性的介绍,后面将通过实例为大家演示。
本节演示的代码可参考这里
- 简介
Symbol数据类型 - 具有
[Symbol.iterator]属性的数据类型 - 生成
Iterator对象 Generator返回的也是Iterator对象- 接下来...
Symbol是一个特殊的数据类型,和number string等并列,详细的教程可参考阮一峰老师 ES6 入门的 Symbol 篇。先看两句程序
console.log(Array.prototype.slice) // [Function: slice]
console.log(Array.prototype[Symbol.iterator]) // [Function: values]数组的slice属性大家都比较熟悉了,就是一个函数,可以通过Array.prototype.slice得到。这里的slice是一个字符串,但是我们获取Array.prototype[Symbol.iterator]可以得到一个函数,只不过这里的[Symbol.iterator]是Symbol数据类型,不是字符串。但是没关系,Symbol数据类型也可以作为对象属性的key。如下:
var obj = {}
obj.a = 100
obj[Symbol.iterator] = 200
console.log(obj) // {a: 100, Symbol(Symbol.iterator): 200}在此小节中,你只需要知道[Symbol.iterator]是一个特殊的数据类型Symbol类型,但是也可以像number string类型一样,作为对象的属性key来使用
在 ES6 中,原生具有[Symbol.iterator]属性数据类型有:数组、某些类似数组的对象(如arguments、NodeList)、Set和Map。其中,Set和Map也是 ES6 中新增的数据类型。
// 数组
console.log([1, 2, 3][Symbol.iterator]) // function values() { [native code] }
// 某些类似数组的对象,NoeList
console.log(document.getElementsByTagName('div')[Symbol.iterator]) // function values() { [native code] }原生具有[Symbol.iterator]属性数据类型有一个特点,就是可以使用for...of来取值,例如
var item
for (item of [100, 200, 300]) {
console.log(item)
}
// 打印出:100 200 300
// 注意,这里每次获取的 item 是数组的 value,而不是 index ,这一点和 传统 for 循环以及 for...in 完全不一样而具有[Symbol.iterator]属性的对象,都可以一键生成一个Iterator对象。如何生成以及生成之后什么样子,还有生成之后的作用,下文分解。
不要着急,也不要跳过本文的任何步骤,一步一步跟着我的节奏来看。
定义一个数组,然后生成数组的Iterator对象
const arr = [100, 200, 300]
const iterator = arr[Symbol.iterator]() // 通过执行 [Symbol.iterator] 的属性值(函数)来返回一个 iterator 对象好,现在生成了iterator,那么该如何使用它呢 ———— 有两种方式:next和for...of。
先说第一种,next
console.log(iterator.next()) // { value: 100, done: false }
console.log(iterator.next()) // { value: 200, done: false }
console.log(iterator.next()) // { value: 300, done: false }
console.log(iterator.next()) // { value: undefined, done: true }看到这里,再结合上一节内容,是不是似曾相识的感觉?(额,没有的话,那你就回去重新看上一节的内容吧) iterator对象可以通过next()方法逐步获取每个元素的值,以{ value: ..., done: ... }形式返回,value就是值,done表示是否到已经获取完成。
再说第二种,for...of
let i
for (i of iterator) {
console.log(i)
}
// 打印:100 200 300 上面使用for...of遍历iterator对象,可以直接将其值获取出来。这里的“值”就对应着上面next()返回的结果的value属性
看到这里,你大体也应该明白了,上一节演示的Generator,就是生成一个Iterator对象。因此才会有next(),也可以通过for...of来遍历。拿出上一节的例子再做一次演示:
function* Hello() {
yield 100
yield (function () {return 200})()
return 300
}
const h = Hello()
console.log(h[Symbol.iterator]) // [Function: [Symbol.iterator]]执行const h = Hello()得到的就是一个iterator对象,因为h[Symbol.iterator]是有值的。既然是iterator对象,那么就可以使用next()和for...of进行操作
console.log(h.next()) // { value: 100, done: false }
console.log(h.next()) // { value: 200, done: false }
console.log(h.next()) // { value: 300, done: false }
console.log(h.next()) // { value: undefined, done: true }
let i
for (i of h) {
console.log(i)
}这一节我们花费很大力气,从Iterator又回归到了Generator,目的就是为了看看Generator到底是一个什么东西。了解其本质,才能更好的使用它,否则总有一种抓瞎的感觉。
接下来我们就Generator具体有哪些使用场景。
如果你看完了,感觉还不错,欢迎给我打赏 ———— 以激励我更多输出优质内容
