“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情”
Generator函数是ES6引入的,主要用于异步编程,Generator最大特点就是可以交出函数的执行权(即暂停执行)
Generator函数与普通函数的区别
- function关键字与函数名之间有一个星号
- Generator函数体内部使用yield语句,定义不同的内部状态(函数内部的值,在不同的时候,是不一样的)
本质上,整个Generator函数就是一个封装的异步任务,或者说是异步任务的容器。
最简单的Generator函数
使用.next()方法让它动起来,可以把next理解为是一个“启动方法”,作用是分阶段地执行Generator函数
每次调用.next()方法,会返回一个对象,表示当前阶段的信息,value属性、done属性
done属性的值有true和false,true表示函数执行完了,false表示函数没执行完
function* fn() {
yield "a";
yield "b";
yield "c";
return "d";
}
let _fn = fn(); // 调用函数,返回一个迭代器对象
console.log(_fn.next()); // {value: 'a', done: false}
console.log(_fn.next()); // {value: 'b', done: false}
console.log(_fn.next()); // {value: 'c', done: false}
console.log(_fn.next()); // {value: 'd', done: true}
console.log(_fn.next()); // {value: undefined, done: true}
迭代器之间作用域独立
注:yield只能用在Generator函数里,普通函数不行
function* fn() {
var _n = 1;
yield ++_n;
yield ++_n;
yield ++_n;
}
var aa = fn(); // aa为迭代器1的引用
var bb = fn(); // bb为迭代器2的引用
console.log(aa.next()); // {value: 2, done: false}
console.log(aa.next()); // {value: 3, done: false}
console.log(bb.next()); // {value: 2, done: false}
console.log(aa.next()); // {value: 4, done: false}
从上面aa、bb两个迭代器的运行结果来看,每个迭代器之间是相互独立的,作用域独立。
每当你调用了一个迭代器内部的.next()方法,Generator函数内部的指针,就是从上一次停下的地方,继续运行,直到遇到下一个yield语句
next方法传参
Generator函数中的next方法可以接收参数
- 传入的参数,其实是把上一个yield语句的返回值给覆盖了
- 第一个next方法其实是启动器,在它之前没有yield语句,给第一个next方法传参没意义
function* fn() {
var _n = 1;
var _v = yield _n + 22;
console.log("aa", _v);
yield ++_n;
yield ++_n;
}
var _fn = fn();
console.log(_fn.next()); // {value: 23, done: false}
_fn.next("abc"); // aa abc
console.log(_fn.next()); // {value: 3, done: false}
这个例子,是最能说明Generator函数的用途的例子,就是可以通过next方法,去分阶段的注入数据,让函数分阶段的给出不同的返回值
for...of
Generator函数,支持for of 循环,用来迭代Generator函数在执行时,生成的那个迭代对象
function* fn() {
yield "a";
yield "b";
yield "c";
return "d";
}
var _fn = fn();
for (var i of _fn) {
console.log(i); // 依次输出 a b c
}