摘要:迭代器協議當一個對象被認為是一個迭代器時,它實現了一個的方法。該方法返回一個對象包含和屬性,的值表示迭代器是否可以產生序列中的下一個值,為迭代器返回的任何值。
iterator 可遍歷(可迭代)協議
一個對象為了變成可遍歷對象,比如說可以用 for ... in 結構遍歷其屬性值,必須實現 @@iterator 方法, 意思是這個對象(或者它原型鏈 prototype chain 上的某個對象)必須有一個名字是 Symbol.iterator 的屬性。
屬性 | 值 |
---|---|
[Symbol.iterator] | 返回一個對象的無參函數,被返回對象符合可遍歷協議。 |
當一個對象被認為是一個迭代器時,它實現了一個 next() 的方法。
該方法返回一個對象包含 done 和 value 屬性,done 的值表示迭代器是否可以產生序列中的下一個值,value 為迭代器返回的任何 JavaScript 值。done 為 true 時可省略。
let a = { q: "q", w: "w", e: "e", }; Object.defineProperty(a, length, { enumerable: false, value: 3 });
現在對 a 嘗試用 for ... in 結構遍歷其屬性值
for (let v of a) { console.log(v); }
報錯:
Uncaught TypeError: a[Symbol.iterator] is not a function
定義一個函數利用閉包實現一個將 a 轉變為可迭代對象
function Iterator(obj) { let i; return ()=> { return { next: ()=> { if (i < obj.length) { for (i in obj) { return { done: false, value: obj[i] }; } } return { done: true }; } }; }; } a[Symbol.iterator] = Iterator(a);generator
Generator 函數最大特點就是可以交出函數的執行權(即暫停執行)。異步操作需要暫停的地方,都用 yield 語句注明。調用 Generator 函數并不會執行本體,而是每次調用 next 方法的時候,執行到下一個碰到的 yield 處。
Generator 函數的數據交換function* anotherGenerator(i) { yield i + 1; let x = yield i + 2; yield x + 3; } function* generator(i){ yield i; yield* anotherGenerator(i); // 執行權轉交給另一個 generator 函數的話 yield 后面帶星號,直接調用的話是沒有效果的 yield i + 10; } var gen = generator(10); console.log(gen.next().value); // 10 console.log(gen.next().value); // 11 console.log(gen.next().value); // 12 console.log(gen.next(2).value); // 5 console.log(gen.next().value); // 20 // next 的返回值和迭代器的 next 類似,yield 語句的執行結果作為 value,是否還有下一個 yield 決定 done // next 方法可以帶有參數,這個參數可以傳入 Generator 函數,作為上個階段異步任務的返回結果Generator 函數的錯誤處理
Generator 函數內部還可以部署錯誤處理代碼,捕獲函數體外拋出的錯誤。
function* gen(x){ try { var y = yield x + 2; } catch (e){ console.log(e); } return y; } var g = gen(1); g.next(); g.throw("出錯了"); // 出錯了
上面代碼的最后一行,Generator 函數體外,使用指針對象的 throw 方法拋出的錯誤,可以被函數體內的 try ... catch 。
Generator 函數的終止Generator函數返回的遍歷器對象,還有一個return方法,可以返回給定的值,并且終結遍歷Generator函數。
function* gen() { yield 1; yield 2; yield 3; } var g = gen(); g.next() // { value: 1, done: false } g.return("foo") // { value: "foo", done: true } g.next() // { value: undefined, done: true }
如果Generator函數內部有try...finally代碼塊,那么return方法會推遲到finally代碼塊執行完再執行。
function* numbers () { yield 1; try { yield 2; yield 3; } finally { yield 4; yield 5; } yield 6; } var g = numbers() g.next() // { done: false, value: 1 } g.next() // { done: false, value: 2 } g.return(7) // { done: false, value: 4 } g.next() // { done: false, value: 5 } g.next() // { done: true, value: 7 }
上面代碼中,調用return方法后,就開始執行finally代碼塊,然后等到finally代碼塊執行完,再執行return方法。
Generator 函數的自動執行co 庫是tj寫的一個讓Generator函數自動執行的工具。
let co = require("co"); let p = co(gen); p.then(function (){ console.log("ok"); })
co 函數返回一個 Promise 對象,因此可以用 then 方法添加回調函數。
async 與 awaitES7 為 generator 的語法糖
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/87777.html
摘要:數據的層級意味著迭代數據結構并提取它的數據。對于技術人而言技是單兵作戰能力,術則是運用能力的方法。在前端娛樂圈,我想成為一名出色的人民藝術家。 聊聊 for of 說起 for of 相信每個寫過 JavaScript 的人都用過 for of ,平時我們用它做什么呢?大多數情況應該就是遍歷數組了,當然,更多時候,我們也會用 map() 或者 filer() 來遍歷一個數組。 但是就...
摘要:返回的遍歷器對象可以依次遍歷函數內部的每一個狀態。示例內部捕獲外部捕獲內部捕獲外部捕獲上面代碼遍歷器對象連續拋出兩個錯誤,第一個被函數體內的捕獲。上面代碼中,首先執行函數,獲取遍歷器對象,然后使用方法第二行,執行異步任務的第一階段。 參考 來源《ecmascript6 入門》generator部分 認識generator函數 形式上,generator函數有兩個特點:一是functio...
摘要:舉個例子遍歷器生成函數,作用就是返回一個遍歷器對象,方法返回一個對象,表示當前數據成員的信息。該對象本身也具有屬性,執行后返回自身。 Iterator的作用 一是為各種數據結構,提供一個統一的、簡便的訪問接口;(統一)二是使得數據結構的成員能夠按某種次序排列;(按序)三是ES6創造了一種新的遍歷命令for...of循環,Iterator接口主要供for...of消費。舉個例子:遍歷器生...
摘要:舉個例子遍歷器生成函數,作用就是返回一個遍歷器對象,方法返回一個對象,表示當前數據成員的信息。該對象本身也具有屬性,執行后返回自身。 Iterator的作用 一是為各種數據結構,提供一個統一的、簡便的訪問接口;(統一)二是使得數據結構的成員能夠按某種次序排列;(按序)三是ES6創造了一種新的遍歷命令for...of循環,Iterator接口主要供for...of消費。舉個例子:遍歷器生...
閱讀 1628·2021-09-08 10:42
閱讀 3611·2021-08-11 10:23
閱讀 3982·2019-08-30 14:10
閱讀 2740·2019-08-29 17:29
閱讀 3097·2019-08-29 12:50
閱讀 647·2019-08-26 13:36
閱讀 3463·2019-08-26 11:59
閱讀 1494·2019-08-23 16:23