日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js中的generator

發布時間:2024/1/23 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js中的generator 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

generator(生成器)是ES6標準引入的新的數據類型。一個generator看上去像一個函數,但可以返回多次。

ES6定義generator標準的哥們借鑒了Python的generator的概念和語法,如果你對Python的generator很熟悉,那么ES6的generator就是小菜一碟了。如果你對Python還不熟,趕快惡補Python教程!。

我們先復習函數的概念。一個函數是一段完整的代碼,調用一個函數就是傳入參數,然后返回結果:

function foo(x) {return x + x; }var r = foo(1); // 調用foo函數

函數在執行過程中,如果沒有遇到return語句(函數末尾如果沒有return,就是隱含的return undefined;),控制權無法交回被調用的代碼。

generator跟函數很像,定義如下:

function* foo(x) {yield x + 1;yield x + 2;return x + 3; }

generator和函數不同的是,generator由function*定義(注意多出的*號),并且,除了return語句,還可以用yield返回多次。

大多數同學立刻就暈了,generator就是能夠返回多次的“函數”?返回多次有啥用?

還是舉個栗子吧。

我們以一個著名的斐波那契數列為例,它由0,1開頭:

0 1 1 2 3 5 8 13 21 34 ...

要編寫一個產生斐波那契數列的函數,可以這么寫:

function fib(max) {vart,a = 0,b = 1,arr = [0, 1];while (arr.length < max) {t = a + b;a = b;b = t;arr.push(t);}return arr; }// 測試: fib(5); // [0, 1, 1, 2, 3] fib(10); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

函數只能返回一次,所以必須返回一個Array。但是,如果換成generator,就可以一次返回一個數,不斷返回多次。用generator改寫如下:

function* fib(max) {vart,a = 0,b = 1,n = 1;while (n < max) {yield a;t = a + b;a = b;b = t;n ++;}return a; }

直接調用試試:

fib(5); // fib {[[GeneratorStatus]]: "suspended", [[GeneratorReceiver]]: Window}

直接調用一個generator和調用函數不一樣,fib(5)僅僅是創建了一個generator對象,還沒有去執行它。

調用generator對象有兩個方法,一是不斷地調用generator對象的next()方法:

var f = fib(5); f.next(); // {value: 0, done: false} f.next(); // {value: 1, done: false} f.next(); // {value: 1, done: false} f.next(); // {value: 2, done: false} f.next(); // {value: 3, done: true}

next()方法會執行generator的代碼,然后,每次遇到yield x;就返回一個對象{value: x, done: true/false},然后“暫停”。返回的value就是yield的返回值,done表示這個generator是否已經執行結束了。如果done為true,則value就是return的返回值。

當執行到done為true時,這個generator對象就已經全部執行完畢,不要再繼續調用next()了。

第二個方法是直接用for ... of循環迭代generator對象,這種方式不需要我們自己判斷done:

for (var x of fib(5)) {console.log(x); // 依次輸出0, 1, 1, 2, 3 }

generator和普通函數相比,有什么用?

因為generator可以在執行過程中多次返回,所以它看上去就像一個可以記住執行狀態的函數,利用這一點,寫一個generator就可以實現需要用面向對象才能實現的功能。例如,用一個對象來保存狀態,得這么寫:

var fib = {a: 0,b: 1,n: 0,max: 5,next: function () {varr = this.a,t = this.a + this.b;this.a = this.b;this.b = t;if (this.n < this.max) {this.n ++;return r;} else {return undefined;}} };

用對象的屬性來保存狀態,相當繁瑣。

generator還有另一個巨大的好處,就是把異步回調代碼變成“同步”代碼。這個好處要等到后面學了AJAX以后才能體會到。

沒有generator之前的黑暗時代,用AJAX時需要這么寫代碼:

ajax('http://url-1', data1, function (err, result) {if (err) {return handle(err);}ajax('http://url-2', data2, function (err, result) {if (err) {return handle(err);}ajax('http://url-3', data3, function (err, result) {if (err) {return handle(err);}return success(result);});}); });

回調越多,代碼越難看。

有了generator的美好時代,用AJAX時可以這么寫:

try {r1 = yield ajax('http://url-1', data1);r2 = yield ajax('http://url-2', data2);r3 = yield ajax('http://url-3', data3);success(r3); } catch (err) {handle(err); }

看上去是同步的代碼,實際執行是異步的。

練習

要生成一個自增的ID,可以編寫一個next_id()函數:

var current_id = 0;function next_id() {current_id ++;return current_id; }

由于函數無法保存狀態,故需要一個全局變量current_id來保存數字。

不用閉包,試用generator改寫:

'use strict'; function* next_id() { }// 測試: varx,pass = true,g = next_id(); for (x = 1; x < 100; x ++) {if (g.next().value !== x) {pass = false;alert('測試失敗!');break;} } if (pass) {alert('測試通過!'); } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的js中的generator的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。