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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

从 for of 聊到 Generator

發布時間:2025/6/17 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从 for of 聊到 Generator 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

你能學到什么

  • 對 for of 更深入的理解
  • iterator 到底是何方神圣?
  • 數組也是對象,為什么不能用 for of 來遍歷對象呢?
  • 如何實現對象的 for of?
  • Generator 又是何方神圣?
  • Generator 有什么用呢?

聊聊for of

說起 for of 相信每個寫過 JavaScript 的人都用過 for of ,平時我們用它做什么呢?大多數情況應該就是遍歷數組了,當然,更多時候,我們也會用 map() 或者 filer() 來遍歷一個數組。 但是就像我們標題里面說的,它跟 Generator 能扯上什么關系呢?

首先我們想一個問題,為什么使用 for of 或者 map() / filer() 方法就可以遍歷一個數組 (或者類數組對象: Strings , Maps , Sets , arguments ) 呢? 為什么不能用他們來遍歷一個對象呢?

在真正揭開謎底之前,站在 for of 的角度想一下,現在讓你去遍歷一個數組,你需要知道什么信息呢?

  • 對應下標的值
  • 是否遍歷結束的標志

帶著這樣的思考,我們打印一個數組來看看這里面的玄機:

const numbersArray = [1, 2, 3];console.dir(numbersArray); 復制代碼

?

?

數組 (或者類數組對象: Strings , Maps , Sets , arguments ) 的原型中都實現了一個方法 Symbol.iterator,問題來了,那么這個 Symbol.iterator 又有什么用呢? 拿出來試一下就知道了:

let iterator = numbersArray[Symbol.iterator](); // 我們把這個 Symbol.iterator 打印一下看看里面到底有些什么 console.dir(iterator); 復制代碼

?

?

這里有一個 next() 方法對嗎?執行這個 next() 方法:

iterator.next(); // 輸出 {value: 1, done: false} iterator.next(); // 輸出 {value: 2, done: false} iterator.next(); // 輸出 {value: 3, done: false} iterator.next(); // 輸出 {value: undefined, done: true} 復制代碼

請注意,當下標超出時,value: undefined

我們發現這個 iterator.next() 每次都返回了一個對象。這對象包含兩個信息:當前下標的值,以及遍歷是否結束的標志。這印證了我們之前思考,有了這兩個信息,你作為 for of 函數,也能打印出數組的每一項了不是嗎?

新的問題來了,iterator 到底是何方神圣呢?

iterator(迭代器) & The iterator protocol(迭代協議)

聊到了 iterator 我們不得不先說一下 The iterator protocol(迭代協議)

" The iterable protocol allows JavaScript objects to define or customize their iteration behavior " - MDN

MDN 上是這么說的:The iterator protocol 允許 JavaScript 對象去定義或定制它們的迭代行為 ,所以上面出現的 Symbol.iterator 這個方法,就是數組對于這個協議的實現。那么按照這個協議,數組是怎么實現了一個 iterator 呢?

"In JavaScript an iterator is an object which defines a sequence and potentially a return value upon its termination. More specifically an iterator is any object which implements the Iterator protocol by having a next() method which returns an object with two properties: value, the next value in the sequence; and done, which is true if the last value in the sequence has already been consumed. If value is present alongside done, it is the iterator's return value." - MDN

這一大段看起來比較費勁,簡單來說就像我們上一章節所印證的,它實現的方式是定義了一個 next() 方法,而這個 next() 方法每次被執行都會返回一個對象: {value:xxx/undefined , done: true/false } 其中 value 代表的是當前遍歷到的值,done 代表是否遍歷結束。

本小節回答了我們之前的提問: 為什么不能用 for of 來遍歷一個對象呢? 原因很簡單:JavaScript 的對象中沒有實現一個這樣的 iterator 。你可以打印一個對象來看看結果如何:

console.dir({ a: 1, b: 2 }); 復制代碼

?

?

okay, 到這里如果就結束的話,那我們了解得還不夠深入,于是再問一個問題:

Why is there no built-in object iteration ? (為什么在 object 中沒有內置迭代器呢? )

為什么在 object 中沒有內置迭代器呢?

對啊,為什么呢? 我們在各樣的場景中也需要來遍歷一個對象啊?為什么沒有內置一個迭代器呢?要回答這個問題,我們得從另外一個角度出發,了解一些基本的概念:

我們常常說遍歷對象,但是簡單來說,只會在兩種層級上來對一個 JavaScript 對象進行遍歷:

  • 程序的層級 - 什么意思呢?在程序層級上,我們對一個對象進行迭代,是在迭代展示其結構的對象屬性。 可能還不是很好理解,舉個栗子:Array.prototype.length 這個屬性與對象的結構相關,但卻不是它的數據。

  • 數據的層級 - 意味著迭代數據結構并提取它的數據。舉個栗子:我們在迭代一個數組的時候,迭代器是對于它的 每一個數據進行迭代,如果 array = [a, b, c, d] 那么迭代器訪問到的是 1, 2, 3, 4。

明白了這個緣由,JavaScript 雖然不支持用 for of 來遍歷對象,但是提供了一個 for in 方法來遍歷所有非 Symbol 類型并且是可枚舉的屬性。

標準不支持,如果我們就是要用 for-of 來遍歷對象呢?那我們可以任性的實現一個啊:

Object.prototype[Symbol.iterator] = function*() {for (const [key, value] of Object.entries(this)) {yield { key, value };} }; 復制代碼 for (const { key, value } of { a: 1, b: 2, c: 3 }) {console.log(key, value); } 復制代碼

不知道你有沒有注意一個細節,在我們任性的實現一個 iterator 的代碼中,我們用到了一個很奇怪的結構 function*() {} ,這個就是我們接下來要介紹的 Generator

Generators

看到這個名字覺得很厲害哈,但其實很簡單,寫一個 Generator 你只需要在函數名和 function 關鍵字中間加一個 * 號就可以了。至于里面的 yield 是什么,后面會說的。

talk is cheap , show me the code ,用一個例子,簡單說一下概念。

我們現在定義了一個這樣的 Generator 叫做 gen

function* gen() {yield 1;yield 2;yield 3;yield 4; } 復制代碼

我們只能看到,這里面有 4 個語句,那打印一下看看唄:

?

?

這里發現了一個熟悉的函數,next() 方法,我們把 gen 實例化一下,執行一下它的 next() 來看看結果:

?

?

還是熟悉的味道,那么到這里,我們已經知道,Generator 可以實例化出一個 iterator ,并且這個 yield 語句就是用來中斷代碼的執行的,也就是說,配合 next() 方法,每次只會執行一個 yield 語句。

多說一句,針對 Generator 本身,還有一個有意思的特性,yield 后面可以跟上另一個 Generator 并且他們會按照次序執行:

function* gen() {yield 1;yield* gen2();return; }function* gen2() {yield 4;yield 5; }let iterator = gen(); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); console.log(iterator.next()); 復制代碼

?

?

結果很有意思不是嗎?而且 return 會終結整個 Generator ,換句話說:寫在 return 后面的 yield 不會執行。

Generator 有什么用?

Generator 有什么用? 聰明的同學可能已經猜到了,是的,它能夠中斷執行代碼的特性,可以幫助我們來控制異步代碼的執行順序:

例如有兩個異步的函數 A 和 B, 并且 B 的參數是 A 的返回值,也就是說,如果 A 沒有執行結束,我們不能執行 B。

那這時候我們寫一段偽代碼:

function* effect() {const { param } = yield A();const { result } = yield B(param);console.table(result); } 復制代碼

這時候我們如果需要得到 result 那么我們就需要:

const iterator = effect() iterator.next() iterator.next() 復制代碼

執行兩次 next() 得到結果,看起來很傻不是嗎?有沒有好的辦法呢?(廢話,肯定有啊) 假設你在每次執行 A() / B() 的請求結束之后,都會自動執行 next() 方法呢?這不就解決了嗎?

這樣的庫早就存在了,建議大家參考 co 的源碼,當然你也可以通過閱讀 這篇文章 來看看,到底 Generator 是怎么玩的。


ps:

https://blog.csdn.net/zshdd/article/details/82897452?

Generator函數自動執行

function readFile(fileName) {
? ? return new Promise(function (resolve,reject) {
? ? ? ? fs.readFile(fileName,function (err,data) {
? ? ? ? ? ? if(err) reject(err);
? ? ? ? ? ? resolve(data.toString());
? ? ? ? })
? ? })
}
function* gentT2() {
? ? var f1 = yield readFile('ip.txt');
? ? var f2 = yield readFile('ip1.txt');
? ? console.log(f1,f2);
}
function run(gen) {
? ? var g=gen();
? ? function next(data) {
? ? ? ? var res=g.next(data);
? ? ? ? if(res.done) return res.value;
? ? ? ? res.value.then(function (data) {
? ? ? ? ? ? next(data);
? ? ? ? });
? ? }
? ? next();
}
run(gentT2);
// 方便的自動執行generator函數 類似的庫(co)

?

?

深入理解js中的yield

https://www.jianshu.com/p/36c74e4ca9eb

  • yield是ES6的新關鍵字,使生成器函數執行暫停,yield關鍵字后面的表達式的值返回給生成器的調用者。它可以被認為是一個基于生成器的版本的return關鍵字。
  • yield關鍵字實際返回一個IteratorResult(迭代器)對象,它有兩個屬性,value和done,分別代表返回值和是否完成。
  • yield無法單獨工作,需要配合generator(生成器)的其他函數,如next,懶漢式操作,展現強大的主動控制特性。

?

轉載于:https://my.oschina.net/jack088/blog/3003009

總結

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

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