从语法上来说,能够将它理解成状态机,封装了多个内部状态。javascript
Generator函数是ES6提供的一种异步编程解决方案,语法与传统函数彻底不一样。 执行Generator函数会返回一个遍历器对象。 返回的遍历器对象能够依次遍历Generator函数内部的每个状态。java
function* generator () {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = generator();
复制代码
函数并不执行,返回的是指向内部状态的指针对象。 如何执行?编程
hw.next();
复制代码
这个next()底层是什么样的呢?异步
function makeNext(array) {
var nextIndex = 0;
return {
next: function(){
return nextIndex < array.length ?
{value:array[nextIndex++],done:true}:
{value:undefined,done:false}
}
}
}
let makenext = makeNext(['a','b']);
makenext.next();
复制代码
执行时,遇到yield就暂停,返回的对象包括value和done两个属性。 value是yield语句后面表达式的值,done后为布尔类型的值。 最后一次调用next()方法,返回的是{value:undefined,done:false}.ide
Generator返回的遍历器对象,只有调用next()方法才能遍历到下一个内部状态,因此,实际上是提供了一种能够暂停执行的函数,yield就是暂停标志。 next()方法运行逻辑:异步编程
那就编程的单纯的暂缓执行函数函数
function* fn() {
console.log(111)
}
var f= fn();
setTimeout(function() {
f.next();
},2000)
复制代码
很方便有没有! 不过,普通函数不能用yield,用了也报错。 固然,表达式中用的时候,也要加括号。ui
function* fn() {
console.log("hello" + (yield 111));
}
复制代码
固然了,用在函数参数中和赋值语句的右边,是不用加括号的。spa
yield语句自己没有返回值,或者说老是返回undefined。next方法能够带有一个参数,该参数会被看成上一条yield语句的返回值。指针
function* fn (x) {
var y = 2*(yield (x+1));
var z = yield (y/3);
return (x+y+z);
}
var f = fn(5);
f.next();
f.next();
f.next();
var ff = fn(5);
ff.next();
ff.next(12);
ff.next(13);
复制代码
for...of循环能够自动遍历Generator函数生成的遍历器对象,且此时再也不须要调用next方法。
function* fn() {
yield 1;
yield 2;
yield 3;
yield 4;
return 5;
}
for(let v of fn()){
console.log(v);
}
//1 2 3 4
复制代码
为啥没有5? 原来,一旦next方法返回的对象的done属性为true,for...of循环就会终止,且不包括该返回的对象。
function* fibonacci() {
let [pre,curr] = [0,1];
for(;;){
[pre,curr] = [curr,pre+curr];
yield curr;
}
}
for(let i of fibonacci()){
if(i>1000) break;
console.log(i);
}
复制代码
function* loadUI () {
show();
yield loadUI();
hide();
}
var load = loadUI();
//加载
load.next();
//隐藏
load.next();
复制代码
充分利用暂停执行的效果,虽然没在代码中真正实现过,可是属实好用呀!!! 就到这....