- Iterator 是什么,能做什么?
- Generator 是什么,能做什么?
Iterator
Iterator 概念
- iterator 是一种接口机制,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署了 iterator 接口就可以完成遍历操作
Iterator 作用
- 为各种数据结构提供一个统一的简便的访问接口
- 使得数据结构的成员能够按照某种次序排列
- ES6 创造了一种新的遍历命令 for...of 循环,iterator 接口主要供 for...of 消费
Iterator 遍历过程
- 创建一个指针对象,指向当前数据结构的起始位置。也就是说遍历器对象本质上就是一个指针对象
- 第一次调用指针对象的 next 方法,可以将指针指向数据结构的第一个成员
- 第二次调用指针对象的 next 方法,指针就指向数据结构的第二个成员
- 不断调用指针对象的 next 方法,直到它指向数据结构的结束位置
简单实现 Array 的 Iterator 接口调用
let arr = ['a', 'b', 'c']
let iteratorFun = function(arr) {
let nextIndex = 0
return {
next: function() {
return nextIndex < arr.length ? {
value: arr[nextIndex++],
done: false
} : {
value: undefined,
done: true
}
}
}
}
let it = iteratorFun(arr)
console.log(it.next()) // {value: "a", done: false}
console.log(it.next()) // {value: "b", done: false}
console.log(it.next()) // {value: "c", done: false}
console.log(it.next()) // {value: undefined, done: true}
默认 Iterator 接口
- ES6 规定,默认的 iterator 接口部署在数据结构的 Symbol.iterator 属性。也就是说一个数据结构只要有 Symbol.iterator 属性,就认为是可遍历的 iterable
- Symbol.iterator 属性本身是一个函数,就是当前数据结构默认的遍历器生成函数,执行这个函数就会返回一个遍历器
let arr = ['a', 'b', 'c']
let it = arr[Symbol.iterator]()
console.log(it.next()) // {value: "a", done: false}
console.log(it.next()) // {value: "b", done: false}
console.log(it.next()) // {value: "c", done: false}
console.log(it.next()) // {value: undefined, done: true}
Generator
Generator 概念、作用
- ES6 提供的解决异步编程的方案之一
- Generator 是一个状态机,内部封装了不同状态的数据
- 用来生成遍历器对象
- 可暂停函数 ( 惰性求值 ),yield 可暂停,next 方法可启动,每次返回的是 yield 后的表达式结果
- Generator 可以控制函数的执行,代替回调函数解决回调地狱问题
Generator 执行流程
function *fun1(x) {
let y = 2 * (yield(x + 1))
let z = yield(y / 3)
return x + y + z
}
let doit = fun1(5)
console.log(doit.next()) // {value: 6, done: false}
console.log(doit.next(12)) // {value: 8, done: false}
console.log(doit.next(13)) // {value: 42, done: true}
- 首先 Generator 函数调用和普通函数不同,它会返回一个迭代器
- 当执行第一次 next 时,传参会被忽略,并且函数暂停在 yield (x + 1) 处,所以返回 5 + 1 = 6
- 当执行第二次 next 时,传入的参数等于上一个 yield 的返回值,如果你不传参,yield 永远返回 undefined。此时 let y = 2 * 12,所以第二个 yield 等于 2 * 12 / 3 = 8
- 当执行第三次 next 时,传入的参数会传递给 z,所以 z = 13, x = 5, y = 24,相加等于 42
Generator 用法实例
- 用 Generator 生成器来达到 Promise 的效果,控制 ajax 工作流,代码有更好的可读性,从上到下,一气呵成。示例如下:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function ajax(url) { // 创建 ajax 请求流程
axios.get(url).then(res => userGen.next(res.data));
}
function* steps() { // 创建生成器函数
console.log('ajax start users')
const users = yield ajax('https://api.github.com/users');
console.log(users, 'ajax start firstUser')
const firstUser = yield ajax(`https://api.github.com/users/${users[0].login}`);
console.log(firstUser, 'ajax start followers')
const followers = yield ajax(firstUser.followers_url);
console.log(followers, 'ajax end')
}
const userGen = steps();
userGen.next(); // 流程开启
</script>
网友评论