從語法上來說,能夠將它理解成狀態機,封裝了多個內部狀態。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();
複製代碼
充分利用暫停執行的效果,雖然沒在代碼中真正實現過,可是屬實好用呀!!! 就到這....