Iterator迭代器
iterator 一种接口/规范 任何数据结构有了它 就拥有可以按顺序遍历或是访问里面值的魔法🪄🧙♀️
iterator语法
const obj = {
[Symbol.iterator]: function(){}
}
iterator迭代器创建了一个指针 最初指向第一条数据 每次调用next()方法指针会不断往后移动
每一次next会返回一个对象 这个对象包含两个 value 和 done
value:当前数据的值
done:表示遍历是否结束 布尔值
对象没有部署该接口 需要手动实现
1.因为对象遍历顺序不好确定
2.map数据结构弥补了它的缺陷 map有iterator接口 所以对对象部署没有必要
手写对象部署iterator
let obj = {...}
obj[Symbol.iterator] = function () {
let keyList = Object.keys(obj),
index = 0;
return {
next(){
return index < keyList.length ?
{ value:{
key: keyList[index],
val: obj[keyList[index++]]
}
}:{done:true}
}
}
}
for(let key of obj){console.log(key)}
generator生成器
生成器的语法是在function和函数名之间有一个* 与yield搭配使用 可以暂缓代码哦😯
ES6新增的语法 用于实现异步编程 是iterator的具体实现方式 可以😌掌控函数的执行
写法:function* foo(){} function *foo(){}
yield只能出现在生成器函数体内
案例
function *foo(x) {
let y = 2 * (yield (x + 1))
let z = yield (y / 3)
return (x + y + z)
}
let it = foo(5)
console.log(it.next()) // => {value: 6, done: false}
console.log(it.next(12)) // => {value: 8, done: false}
console.log(it.next(13)) // => {value: 42, done: true}
解读:
1.第一次执行next 会忽略入参 第一个yield抛出表达式的值5+1=6 暂停
2.第二次执行next 入参等于上一个表达式的值
所以此时y = 2 * 12 = 24 第二个yield暂停 抛出表达式 y/3 = 24/3 = 8
3.第三次执行next 入参等于上一步表达式的值 所以这里z = 13 函数返回x+y+z= 5+24+13=42
async await语法
是生成器的语法糖🍬 更好的语义/适用性 返回值是promise 这个promise下一章总结
await 优点在于处理then的调用链 解决了回调地狱
缺点 await把异步改造成了同步 如果滥用 多个异步代码无依赖性会导致性能上的下降
async => *
await => yield
原理 使用生成器+自动执行器
手写async
function getNum(num){ //promise 模拟异步请求 作用是入参++
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(num+1)
},1000)
})
}
function asyncFn(fn){ //自动执行器
var gen = fn();
function next(data){
var res = gen.next(data)
if(res.done) return res.value
res.value.then( data => { //没有执行完 则递归
next(data)
})
}
next()
}
var fn = function* (){ 生成器函数
var a = yield getNum(1);
var b = yield getNum(a);
console.log(b)
}
asyncFn(fn)