ES6 中的生成器函式介紹
提醒:本文最後更新於 1939 天前,文中所描述的資訊可能已發生改變,請謹慎使用。
今天介紹的是 ES6 中的生成器函式(generator function),目前瀏覽器中只有 Chrome 29+ 支援它,不過還是先要在 about:flags 中「啟用實驗性JavaScript(Enable Experimental JavaScript )」。需要注意的是,Firefox 很早就提供了類似功能,但它實現的是 ES4 語法,最後會介紹。
定義生成器函式
在 ES6 中定義一個生成器函式很簡單,在 function 後跟上「*」即可:
function* foo1() { };
function *foo2() { };
function * foo3() { };
foo1.toString(); // "function* foo1() { }"
foo2.toString(); // "function* foo2() { }"
foo3.toString(); // "function* foo3() { }"
foo1.constructor; // function GeneratorFunction() { [native code] }
呼叫生成器函式會產生一個生成器(generator)。生成器擁有的最重要的方法是 next(),用來迭代:
function* foo() { };
var bar = foo();
bar.next(); // Object {value: undefined, done: true}
上面第 2 行的語句看上去是函式呼叫,但這時候函式程式碼並沒有執行;一直要等到第 3 行呼叫 next 方法才會執行。next 方法返回一個擁有 value 和 done 兩個欄位的物件。
生成器函式通常和 yield 關鍵字同時使用。函式執行到每個 yield 時都會中斷並返回 yield 的右值(通過 next 方法返回物件中的 value 欄位)。下次呼叫 next,函式會從 yield 的下一個語句繼續執行。等到整個函式執行完,next 方法返回的 done 欄位會變成 true。下面看一個簡單的例子:
function* list() {
for(var i = 0; i < arguments.length; i++) {
yield arguments[i];
}
return "done.";
}
var o = list(1, 2, 3);
o.next(); // Object {value: 1, done: false}
o.next(); // Object {value: 2, done: false}
o.next(); // Object {value: 3, done: false}
o.next(); // Object {value: "done.", done: true}
o.next(); // Error: Generator has already finished
可以看到,每次呼叫 next 方法,都會得到當前 yield 的值。函式執行完之後,再呼叫 next 方法會產生異常。
斐波那契數列
在其它語言中,生成器函式和 yield 通常會被用來演示生成斐波那契數列(前兩個數字都是 1 ,除此之外任何數字都是前兩個數之和的數列)。下面是 JavaScript 的生成器函式版本:
function* fab(max) {
var count = 0, last = 0, current = 1;
while(max > count++) {
yield current;
var tmp = current;
current += last;
last = tmp;
}
}
var o = fab(10), ret, result = [];
while(!(ret = o.next()).done) {
result.push(ret.value);
}
console.log(result); // [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
程式碼一目瞭然,不多解釋了。相比常見的遞迴實現,用生成器函式來產生斐波那契數列既高效又直觀。
結合 Promise 使用
我之前寫過一篇《非同步程式設計:when.js 快速上手》,介紹了 Promise 程式設計的一些基礎知識,沒看過的同學可以點過去看完再回來。實際上,生成器函式可以很好的跟 Promise 規範結合起來完成非同步程式設計。直接看例子(在瀏覽器中預覽):
var getData = function() {
var deferred = Q.defer();
$.getJSON(api, function(data){
deferred.resolve(data[0]);
});
return deferred.promise;
}
var getImg = function(src) {
var deferred = Q.defer();
var img = new Image();
img.onload = function() {
deferred.resolve(img);
};
img.src = src;
return deferred.promise;
}
var showImg = function(img) {
$(img).appendTo($('#container'));
}
var all = Q.async(function* () {
var src = yield getData();
var img = yield getImg(src);
showImg(img);
});
all();
前三個函式跟我之前那篇文章裡唯一不同的地方是:when.js 換成了 Q,因為 Q 框架的 async 方法支援生成器函式。關鍵程式碼在最後幾行,Q.async 收到生成器函式,先在內部產生一個生成器;再呼叫生成器的 next() 方法,得到類似這樣的返回值: {'value' : promise / value, 'done' : true / false} ;如果 value 是 promise,Q 會把它放在 when 函式裡執行。Q.async 內部每個 promise 在 resolve 時都會呼叫生成器的 next 方法,直到整個生成器執行完成。
最後
在其它語言中,一般都有方便的迭代器語法,自動呼叫生成器的 next 方法。例如下面是 Python 的「for ... in」:
def fab(max):
count, last, current = 0, 0, 1
while count < max:
yield current
last, current = current, last + current
count = count + 1
for n in fab(10):
print(n)
ES6 也規定了類似的語法「for ... of」用來迭代,現階段的 Chrome 並不支援(已經支援),Firefox 卻支援。看一個只能執行在 Firefox 下的例子(再次說明:現階段 Firefox 的生成器函式未按 ES6 規範實現):
function fab(max) {
var count = 0, last = 0, current = 1;
while(count++ < max) {
yield current;
var tmp = current;
current += last;
last = tmp;
}
}
for(var i of fab(10)) {
console.log(i);
}
參考:
--EOF--
提醒:本文最後更新於 1939 天前,文中所描述的資訊可能已發生改變,請謹慎使用。
相關推薦
ES6 中的生成器函式介紹
提醒:本文最後更新於 1939 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 今天介紹的是 ES6 中的生成器函式(generator function),目前瀏覽器中只有 Chrome 29+ 支援它,不過還是先要在 about:flags 中「啟用實驗性JavaScript(Enabl
ES6中的函式和陣列補漏
物件的函式解構 我們在前後端分離時,後端經常返回來JSON格式的資料,前端的美好願望是直接把這個JSON格式資料當作引數,傳遞到函式內部進行處理。ES6就為我們提供了這樣的解構賦值。 let json={ a:'leiy', b:'ly' } function fun({a,b="yu"})
三十四、ES6中箭頭函式的使用
1、單引數箭頭函式 ES6中允許使用“箭頭”(=>)定義函式: var f = v => v; 以上程式碼相當於: var f = function( v ) { return v; } “箭頭”(=>)後面是函式體,“箭頭”(=>
續(利用tensorflow實現簡單的卷積神經網路-對程式碼中相關函式介紹)——遷移學習小記(三)
上篇文章對cnn進行了一些介紹,附了完整小例子程式碼,介紹了一部分函式概念,但是對我這樣的新手來說,程式碼中涉及的部分函式還是無法一下子全部理解。於是在本文中將對程式碼中使用的函式繼續進行一一介紹。 具體程式碼見上一篇(二) 一、 #定義輸入的placehoder,x是特徵
es6中箭頭函式 注意點
var aaabbb = 'kkkooo' setTimeout(()=>{ var aaaa = 'kkkk'; console.log(this) },1000); 因為據我瞭解,箭頭函式指向是建立時候上下文的this指向,所以天真的認為上述函式中在箭頭函式內部建立的變數
標頭檔案管理 使用#ifndef防止多重包含 部分標頭檔案用途及其中的函式介紹
1、 在同一個檔案中只能將同一個標頭檔案包含一次。記住這個規則很容易,但很可能在不知情的情況下將標頭檔案包含多次。例如,可能使用包含了另一個頭檔案的標頭檔案。有一種標準的C++技術可以避免多次包含同一個標頭檔案。它是基於前處理器編譯指令#ifnd
影象處理中矩形標記影象中某一塊區域matlab中rectangle函式介紹
rectangle('Position',[x,y,w,h]) 從點(x,y)開始繪製一個寬w高h的矩形,對座標軸資料單元指定值。 注意,按指定的比例顯示矩形,需要設定座標軸資料寬高比來使得x和y軸有等長的單位。你可以用命令axis equal 或者daspect([1,
oracle中的函式介紹(一):nvl函式、decode函式、case when函式、sum函式
最近做專案接觸到的oracle資料庫比較多,經常用到裡面的一些函式,以前的部落格中也介紹過行轉列和列轉行,這次再簡單給大家介紹幾個: nvl() NVL(a,b)就是判斷a是否是NULL,如果不
ES5,ES6中箭頭函式,物件定義中this的總結
最近在學ES6的時候,發現使用箭頭函式的時候的this指向不太清楚,和普通的物件建立做了一些對比,講講自己的理解,有問題希望大家和我一起討論研究 箭頭函式 和 function(){}定義的區別,箭頭函式的 這裡的所有程式碼基於chrome進行測試 這裡有幾個帖子是作為參考的
阿里前端測試題--關於ES6中Promise函式的理解與應用
今天做了阿里前端的筆試題目,原題目是這樣的 //實現mergePromise函式,把傳進去的陣列順序先後執行,//並且把返回的資料先後放到陣列data中const timeout = ms => new Promise((resolve, reject) => {setTimeout(() =
ES6中箭頭函式的使用
基本用法 ES6允許使用“箭頭”(=>)定義函式。 var f = v => v; 上面的箭頭函式等同於: var f = function(v) { return v; }; 如果箭頭函式不需要引數或需要多個引數,就使用一個圓括號代表引數部
Python中生成器和叠代器的功能介紹
family line 介紹 mil auto 叠代器 常用 方法 lean 生成器和叠代器的功能介紹 1. 生成器(generator) 1. 賦值生成器 1. 創建 方法:x = (varia
es6中的(=>)箭頭函式
x => x * x 上面的箭頭函式相當於: function (x) { return x * x; } 箭頭函式相當於匿名函式,並且簡化了函式定義。 箭頭函式有兩種格式,一種像上面的,只包含一個表示式,連{ ... }和return都省略掉了。 還有一種可以包含多條語句,這時候就不能省
Es6中Map物件和Set物件的介紹及應用
map和set的方法,工作中有使用到,所以學習一下: Map 物件 Map 物件儲存鍵值對。任何值(物件或者原始值) 都可以作為一個鍵或一個值。 var myMap = new Map(); myMap.set("bar", "baz"); myMap.set(1, "foo"
tensorflow中的control_flow_ops.switch函式介紹
tensorflow中的control_flow_ops模組屬於tensorflow.python.ops中的一個模組,從switch函式的名稱上看就是一個開關函式。 函式:control_flow_ops.switch(data,pred,dtype=None,name=None) 功
ES6中的高階函式:如同 a => b => c 一樣簡單
ES6來啦!隨著越來越多的程式碼庫和思潮引領者開始在他們的程式碼中使用ES6,以往被認為是“僅需瞭解”的ES6特性變成了必需的程式碼常識。這不僅僅是新的語法學習 - 在許多範例中, ES6中新的語言特性可以讓在ES5中寫起來非常麻煩的表達變得更加簡
ES6中的箭頭函式和普通函式有什麼區別?
1、普通函式中的this總是指向呼叫它的那個物件, 箭頭函式沒有自己的this,他的this永遠指向其定義環境,任何方法都改變不了其指向,如call()、bind()、apply()。(正是因為它沒有this,所以也就不能用作建構函式,也沒有原型物件) 2、箭頭函式不能當作建構函
ES6或ES7 中async函式的用法,通過一段程式碼理解它的用法
ES6或ES7 中async函式的用法,一行一行看完程式碼和後面的解釋,應該就會用了吧 首先,如果不懂Promise的用法,那可能你看不懂這裡寫的async的用法。 上面是async使用例子,async是非同步操作的新方案,asyncPrint函式中第21行的
javascript中的一般函式與ES6的箭頭函式對比,以及this指向問題的深度理解
關於this的指向問題,老外有文章寫得非常棒,在看了老外的文章 並結合自己的想法再修改此篇文章 一 、基本概念 本文定義的一般函式 單純 指的是js原生函式(ES5函式) 同時ES5中的作用域只有全域
javascript 中的立即呼叫函式模式、閉包及es6中的塊級作用域
先來看一個在牛客上看到的面試題: 這裡一開始會以為是不就是隔1秒輸出i的值嗎,最後結果就是輸出0~9 的十個數字呀,真的是太young了。 但是真是擼了一遍程式碼,控制檯輸出刺眼的10個10,what? 這個查了資料是說因為這個函式為每一個i都設定了一個計時器,那麼