ES6標準入門之Generator函數(基礎篇)

從語法上來說,能夠將它理解成狀態機,封裝了多個內部狀態。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

yield 表達式

Generator返回的遍歷器對象,只有調用next()方法才能遍歷到下一個內部狀態,因此,實際上是提供了一種能夠暫停執行的函數,yield就是暫停標誌。 next()方法運行邏輯:異步編程

  • 遇到yield語句就暫停執行,並將緊跟在yield語句後面的表達式的值做爲返回對象的value值
  • 下次調用next()方法再繼續往下執行,知道遇到下一個yield語句。
  • 若是沒有在遇到新的yield語句,就一直運行,直到return語句爲止,並將return語句後面的表達式的值做爲返回對象的value值。
  • 若是沒有return語句,則返回的對象的value值是undefined。

yield 與 return 的相同點和區別

  • 相同:都返回緊跟在語句後面的表達式的值
  • 不一樣: 1.yield暫停執行,下次會在當前位置繼續執行,可是return語句不具有記憶功能。 2.yield能夠執行屢次,return只能執行一次。

沒有yield語句的函數

那就編程的單純的暫緩執行函數函數

function* fn() {
  console.log(111)
}
var f= fn();
setTimeout(function() {
 f.next();
},2000)
複製代碼

很方便有沒有! 不過,普通函數不能用yield,用了也報錯。 固然,表達式中用的時候,也要加括號。ui

function* fn() {
    console.log("hello" + (yield 111));
  }
複製代碼

固然了,用在函數參數中和賦值語句的右邊,是不用加括號的。spa

next方法的參數

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);
複製代碼

不想用next

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();
複製代碼

充分利用暫停執行的效果,雖然沒在代碼中真正實現過,可是屬實好用呀!!! 就到這....

相關文章
相關標籤/搜索