“Code tailor”,为前端开发者提供技术相干资讯以及系列根底文章,微信关注“小和山的菜鸟们”公众号,及时获取最新文章。
前言
在开始学习之前,咱们想要告诉您的是,本文章是对阮一峰《ECMAScript6 入门》一书中 “Iterator” 章节的总结,如果您已把握上面常识事项,则可跳过此环节间接进入题目练习
- 什么是 Iterator?有何作用?
- Iterator 是如何遍历的?
- 默认的 Iterator 的接口和罕用场合有哪些?
如果您对某些局部有些忘记,👇🏻 曾经为您筹备好了!
学习链接
Iterator 的学习
汇总总结
概念和作用
JavaScript
示意“汇合”的数据结构,次要是数组(Array
)、对象(Object
),Map
和 Set
。用户能够组合应用它们,定义本人的数据结构,比方数组的成员是 Map
,Map
的成员是对象。这样就须要一种对立的接口机制,来解决所有不同的数据结构。
遍历器(
Iterator
)就是这样一种机制。它是一种接口,为各种不同的数据结构提供对立的拜访机制。任何数据结构只有部署Iterator
接口,就能够实现遍历操作(即顺次解决该数据结构的所有成员)。
作用:
- 为各种数据结构,提供一个对立的、简便的拜访接口
- 使得数据结构的成员可能按某种秩序排列
- ES6 发明了一种新的遍历命令
for...of
循环,Iterator 接口次要供for...of
进行遍历循环。
遍历过程
- 创立一个指针对象,指向以后数据结构的起始地位。也就是说,遍历器对象实质上,就是一个指针对象。
- 第一次调用指针对象的
next
办法,能够将指针指向数据结构的第一个成员。 - 第二次调用指针对象的
next
办法,指针就指向数据结构的第二个成员。 - 一直调用指针对象的
next
办法,直到它指向数据结构的完结地位。
默认 Iterator 接口
Iterator
接口的目标,就是为所有数据结构,提供了一种对立的拜访机制,即 for...of
循环。当应用 for...of
循环遍历某种数据结构时,该循环会主动去寻找 Iterator
接口。一种数据结构只有部署了 Iterator
接口,咱们就称这种数据结构是“可遍历的”。
在 ES6 中有以下几个数据结构具备原生的 Iterator
接口,也就是说,这些数据结构能够间接调用 for...of
进行遍历
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
除了下面这些数据结构,如果须要在别的数据结构中(次要为 Object
)调用 for...of
,则须要本人在 Symbol.iterator
属性下面部署,这样才会被 for...of
循环遍历。定义形式举例如下:
const obj = {[Symbol.iterator]: function () {
return {next: function () {
return {
value: 1,
done: true,
}
},
}
},
}
调用 Iterator 的罕用场合
- 解构赋值
let set = new Set().add('a').add('b').add('c')
let [x, y] = set
// x='a'; y='b'
let [first, ...rest] = set
// first='a'; rest=['b','c']
- 扩大运算符
// 例一
var str = 'hello'
[...str] // ['h','e','l','l','o']
// 例二
let arr = ['b', 'c']
['a', ...arr, 'd']
// ['a', 'b', 'c', 'd']
- yield*
let generator = function* () {
yield 1
yield* [2, 3, 4]
yield 5
}
var iterator = generator()
iterator.next() // { value: 1, done: false}
iterator.next() // { value: 2, done: false}
iterator.next() // { value: 3, done: false}
iterator.next() // { value: 4, done: false}
iterator.next() // { value: 5, done: false}
iterator.next() // { value: undefined, done: true}
理解遍历器如何写
遍历器对象除了具备
next()
办法,还能够具备return()
办法和throw()
办法。如果你本人写遍历器对象生成函数,那么next()
办法是必须部署的,return()
办法和throw()
办法是否部署是可选的。
/*
return() 办法的应用场合是,如果 for...of 循环提前退出(通常是
因为出错,或者有 break 语句),就会调用 return() 办法。如果一个对
象在实现遍历前,须要清理或开释资源,就能够部署 return() 办法。*/
function readLinesSync(file) {
return {[Symbol.iterator]() {
return {next() {return { done: false}
},
return() {file.close()
return {done: true}
},
}
},
}
}
题目自测
一: for in 和 for of 的区别
二: 以下代码会输入什么()
const obj = {2: 5, 3: 6, 4: 7}
obj[Symbol.iterator] = function () {
return {next: function () {if (this._countDown === 3) {return { value: this._countDown, done: true}
}
this._countDown = this._countDown + 1
return {value: obj[this._countDown], done: false }
},
_countDown: 0,
}
}
for (const i of obj) {console.log(i)
}
- A.
2,3,4
- B.
5,6,7
- C.
undefined
,5
,6
- D.
TypeError: obj is not iterable
题目解析
一、
Answer:
正确答案及解析:
for…in | for…of | |
---|---|---|
Applies to | Enumerable Properties | Iterable Collections |
Use with Objects? | Yes | No |
Use with Arrays? | Yes, but not advised | Yes |
Use with Strings? | Yes, but not advised | Yes |
二、
Answer:(C)
obj 是一个一般对象,失常遍历会报错如 D,但下面代码中增加了 Symbol.iterator
属性,所以能够遍历,遍历时看 return
的值为 obj[this._countDown]
,及把每次遍历次数当做键名取值,能够看失去,obj 中只有 2,3,4 这三个键名的键,所以第一次取到的是 undefined,前面失去 5 和 6 所以选 C