Iterator
Iterator:是一种新的遍历机制,它有两个核心。
- 迭代器是一个接口,能快捷的访问数据,通过
Symbol.iterator来创建迭代器, 通过迭代器的next()获取迭代之后的结果。 - 迭代器是用于遍历数据结构的指针(相当于数据库的游标)
const items = ['one', 'two', 'three'];
//获取迭代器
const it = items[Symbol.iterator]();
console.log(it.next());//{value: "one", done: false}
console.log(it.next());//{value: "two", done: false}
console.log(it.next());//{value: "three", done: false}
console.log(it.next());//{value: undefined, done: true}
done如果为false表示遍历继续,如果为true表示遍历完成。
Generator
Generator函数可以通过yield关键字,将函数挂起,为改变执行流提供了可能,同时为做异步编程提供了方案。
Generator函数与普通函数的区别:
function后面,函数名之前加一个*yield关键字只能在Generator函数内部使用
yield
yield关键字使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return关键字。yield关键字实际返回一个IteratorResult对象,它有两个属性,value和done。value属性是对yield表达式求值的结果,而done是false,表示生成器函数尚未完全完成。- 一旦遇到
yield表达式,生成器的代码将被暂停运行,直到生成器的next()方法被调用。每次调用生成器的next()方法时,生成器都会恢复执行。
function* fun() {
console.log('one');
yield 1;
console.log('two');
yield 2;
console.log('three');
}
const it = fun();//函数的调用并不会进入到程序中,它仅仅只返回一个遍历器对象
console.log(it);//fun {<suspended>}
console.log(it.next());//one {value: 1, done: false}
console.log(it.next());//two {value: 2, done: false}
console.log(it.next());//three {value: undefined, done: true}
总结:Generator函数是分段执行的,yield语句是暂停执行,而next()是恢复执行。
next()传参
function* add() {
console.log('one');
let x = yield 1;
console.log('two:' + x);
let y = yield 2;
console.log('three:' + y);
return x + y;
}
const it = add();
console.log(it.next());//one {value: 1, done: false}
console.log(it.next(10));//two:10 {value: 2, done: false}
console.log(it.next(20));//three:20 {value: 30, done: true}
总结: 如果将参数传递给生成器的next()方法,则该值将成为生成器当前yield操作返回的值。即x和y是next()调用,恢复当前yield执行传入的实参的值。
使用场景
为不具备Iterator接口的对象提供了遍历操作
function* objectEntries(obj) {
//获取对象中所有的键
let keys = Object.keys(obj);
for (let key of keys) {
//暂停函数执行
yield [key, obj[key]];
}
}
const obj = {
name: 'tom',
age: 20
};
console.log(obj);//普通对象 {name: "tom", age: 20}
//给对象添加迭代器,并绑定生成器函数
obj[Symbol.iterator] = objectEntries;
console.log(obj);//{name: "tom", age: 20, Symbol(Symbol.iterator): ƒ}
console.log(obj[Symbol.iterator](obj).next());//{value: Array(2), done: false}
//--------------------
for (let [key, value] of objectEntries(obj)) {
console.log(`${key}:${value}`);//name:tom age:20
console.log(key + ":" + value);//name:tom age:20
}
部署ajax操作,让异步代码同步化
function* load() {
loadUI();
yield showData();
hideUI();
}
let it = load();
it.next();
function loadUI() {
console.log('加载loading...页面');
}
function showData() {
//模拟异步操作
setTimeout(() => {
console.log('数据加载完成');
it.next();
}, 1000)
}
function hideUI() {
console.log('隐藏loading...界面');
}
//输出结果
//加载loading...页面
//数据加载完成
//隐藏loading...界面