迭代器 Interator()
Interator() 是es6引入的新的遍历机制,有两个核心:
- 是统一的接口,能快速访问数据,通过
Symbol.interator函数来创建迭代器,通过迭代器的next()方法获取每次迭代的结果 - 迭代器是用于遍历数据结构的指针(数据库的游标),每次
next()迭代指针会向后移,直到返回true表示迭代结束
const items = ['one', 'tow', 'three'];
const ite = items[Symbol.iterator]();
console.log(ite);//Array Iterator {}
console.log(ite.next());//{value: "one", done: false},false表示遍历可以继续
console.log(ite.next());//{value: "tow", done: false}
console.log(ite.next());//{value: "three", done: false}
console.log(ite.next());//{value: undefined, done: false},true表示遍历结束并返回undefined
生成器 Generator()
Generator() 函数可以通过 yield 关键字将函数挂起,为改变函数的执行流提供了可能性,同时为异步编程提供了方案
当声明对象并调用生成器函数后,对象变为一个遍历对象,生成器函数并不执行,而是挂起
fn {<suspended>},对遍历对象使用
next()方法,会开始执行函数,直到yield所在行,返回yield后的变量的值(或执行yield后的函数)和状态false,并挂起生成器,如果后面不再有
yield会继续执行完生成器函数并返回return结果和状态true,没有return则返回undefined
function* fn() {
let a = 1, b = 2, c = 3;
console.log('frist');
yield a;
console.log('second');
yield b;
console.log('third');
yield c;
console.log('end');
}
let fnObj = fn();
console.log(fnObj);//fn {<suspended>} 声明生成器变量,并返回函数状态 - 暂停
console.log(fnObj.next());// frist {value: 1, done: false}
console.log(fnObj);//fn {<suspended>}
console.log(fnObj.next());// second {value: 2, done: false}
console.log(fnObj.next());// third {value: 3, done: false}
console.log(fnObj.next());// end {value: undefined, done: true}
console.log(fnObj);//fn {<closed>} 执行完毕后的生成器对象,返回函数状态 - 关闭
生成器函数与普通函数的区别:
- function后面,函数名之前有个
*表示这是一个生成器函数 - 只能在函数内部使用
yield表达式让函数挂起
总结:Generator() 函数是分段执行的,yield 语句让函数暂停执行,next() 方法让函数恢复执行
next()传参
next() 传入的参数,会向上一个 yield 声明的变量赋值 (所以第一个 next 会忽略第一个传参)
function* fn() {
let a = 1, b = 2, c = 3;
console.log('frist');
let x = yield a;
console.log('second');
let y = yield b + x;
console.log('third');
let z = yield c + y;
console.log('end');
return x + y + z + a + b + c;
}
let fnObj = fn();
console.log(fnObj);//fn {<suspended>}
console.log(fnObj.next());// frist {value: 1, done: false}
console.log(fnObj.next(10));// second {value: 12, done: false}
console.log(fnObj.next(20));// third {value: 23, done: false}
console.log(fnObj.next(30));// end {value: 66, done: true}
Generator() 为不具备Interator接口的对象提供了遍历操作
const obj = {
id: 1,
name: 'Max',
age: 23,
}
obj[Symbol.iterator] = objectEntries;//***通过Symbol.iterator让对象具有迭代器的接口,可以进行遍历操作
console.log(obj);//{id: 1, name: "Max", age: 23, Symbol(Symbol.iterator): ƒ}
function* objectEntries(obj) {
const propKeys = Object.keys(obj);//获取对象的所有key保存到数组[name,age]
for (const propKey of propKeys) {
yield [propKey, obj[propKey]]//for循环[键,对象[键] = 值]
}
}
for (let [key, value] of objectEntries(obj)) {//调用生成器函数并传出obj对象,for循环遍历出键和值
console.log(`${key}:${value}`);
}
应用: Generator()部署ajax异步操作,让异步代码同步化
//加载loading...
//数据加载完成(异步操作)
//隐藏loading...
function loadUI() {
console.log('加载loading...动画');
}
function showData() {
setTimeout(() => { //用setTimeout模拟异步操作
console.log('加载完成');
itLoad.next();//4-数据返回之后调用next()继续执行生成器下一步
}, 1000);
}
function hideUI() {
console.log('隐藏loading...动画');
}
//生成器函数,让异步操作同步化
function* load() {
loadUI();
yield showData();//3-运行到这里挂起并调用showData()函数
hideUI();//5-隐藏loading...
}
let itLoad = load();//1-调用生成器函数声明迭代器对象,生成器函数被挂起
itLoad.next();//2-首次运行生成器函数
ajax 调用
//声明需要进行同步操作的生成器函数
function* main() {
console.log('开始运行');
let res = yield request('https://free-api.heweather.net/s6/weather/now?location=beijing&key=4693ff5ea653469f8bb0c29638035976');
//3-遇到yield语句,挂起并执行request函数,传入api接口
console.log(res);
//后面的操作
console.log('数据请求完成,可以继续操作');
}
//声明ajax调用函数
function request(url) { //4-接收api接口地址
$.ajax({
url,//5-api地址(url:url,接收传入的api参数)
method: 'get',//6-get方法调用
success(res) {
ite.next(res);//把res的值返回给生成器,让生成器继续执行,打印api的返回值
}
})
}
const ite = main();//1-调用生成器函数声明迭代器对象,生成器函数被挂起
ite.next();//2-首次执行生成器函数