迭代器
定义
对于早期的JavaScript表示集合的数据结构,主要是数组和对象,后来ES6中又增加了Map和Set集合。
迭代器(iterator)它是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署了Iterator接口,就可以很方便的完成遍历操作(依次处理该数据结构的所有成员)
作用
- 为JavaScript中各种数据结构,提供统一便捷的访问接口
- 使得数据结构中的成员能按照某个顺序排序
- ES6中提供了一种新的遍历命令
for...of循环,Iterator接口主要供for...of消费
迭代遍历过程
- 创建一个指针对象,指向当前数据结构的起始位置,也就是说,遍历器对象本质上,就是一个指针对象
- 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员
- 第二次调用指针对象的next方法,指针就指向数据结构中的第二个成员
- 不断的调用指针对象的next方法,直到它指向数据结构的结束位置
const makeIterator = (arr) => {
let index = 0
return {
next() {
return index < arr.length ? {
value: arr[index++],
done: false
} : {
value: undefined,
done: true
}
}
}
}
var it = makeIterator(['1', '2'])
console.log(it.next()) // { value: '1', done: false}
console.log(it.next()) // { value: '2', done: false}
console.log(it.next()) // { value: undefined, done: true}
指针对象的next方法,用来移动指针,开始时,指针指向数组的起始位置,然后每次调用next方法,指针就会指向数组下一个成员,第一次调用,指向1,第二次调用指向2。
next方法返回一个对象,表示当前数据的成员信息,这个对象有value和done两个属性,value属性返回当前位置的成员,done属性是一个boolean值,表示遍历是否结束,即是否还有必要进行下一次的next方法的调用,如果value值返回undefined,done返回true则表示遍历完成
具备Ietrator接口的数据
- Array
- String
- Map
- Set
- 函数的arguments参数
- nodeList对象(dom集合对象)
生成器
概念
- generator函数是ES6提供的一种异步编程解决方案,语法与传统的函数完全不一样
- 从语法上,可以理解成generator函数是一个状态机,封装了多个内部状态
- generator函数除了状态机,还是一个遍历器对象生成函数
- generator函数内部,yield可暂停,next方法可启动,每次返回的是yield后的表达式结果
写法
- function函数关键字与函数名直接有个*号
- 函数体内部使用yield表达式,定义不同的内部状态
function* myGenerator() {
console.log('准备执行中...')
yield 'hollo world';
yield 'i am a developer';
}
let MG = myGenerator() // 返回指针对象
const a = MG.next() // {value: "hello", done: false}
const b = MG.next() // { value: 'i am a developer', done: false}
const c = MG.next() // { value: undefined, done: true}
与iterator的关系
JavaScript中对象没有部署Symbol.iterator属性,因此使用for...of遍历时会报错
let obj = { userrName: 'tony', age: 20 }
for (let i of obj) {
console.log(i) // Uncaught TypeError: obj is not iterable
}
由于genrator函数就是一个迭代器生成函数,因此可以把Generator赋值给对象的Symbol.iterator属性,使得该对象具有iterator接口
let obj = { userrName: 'tony', age: 20 }
obj[Symbol.iterator] = function* myTest() {
yield 1;
yield 2;
yield 3;
};
for (let i of obj) {
console.log(i) // 1 2 3
}