JavaScript中的生成器函數詳解

在 JavaScript 中,生成器函數 Generator Function?是一種特殊的函數,它允許你在函數執行過程中暫停和恢復。生成器函數通過 function* 語法定義,并使用 yield 關鍵字來控制函數的執行流程。生成器函數返回一個生成器對象,該對象遵循迭代器協議,可以逐步生成值。

以下是生成器函數的詳細解析:

1. 基本語法

生成器函數使用 function* 定義,函數體內可以使用 yield 關鍵字來暫停函數的執行并返回一個值。

function* myGenerator() {yield 1;yield 2;yield 3;
}

function*:定義生成器函數的關鍵字。

yield:暫停函數執行并返回一個值。每次調用生成器對象的 next() 方法時,函數會從上次暫停的地方繼續執行。

2. 生成器對象

生成器函數調用時不會立即執行函數體,而是返回一個生成器對象。這個生成器對象是一個迭代器,可以通過?next()?方法逐步執行生成器函數。

const gen = myGenerator();console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }

next():恢復生成器函數的執行,直到遇到下一個?yield?或函數結束。

返回一個對象,包含兩個屬性:

value:yield?表達式的值。

done:布爾值,表示生成器函數是否已經執行完畢。

3. yield?關鍵字

yield 是生成器函數的核心關鍵字,它的作用如下:

1. 暫停函數執行:當生成器函數執行到 yield 時,會暫停執行并返回 yield 后面的值;

2. 恢復函數執行:當調用生成器對象的 next() 方法時,函數會從上次暫停的地方繼續執行,直到遇到下一個 yield 或函數結束;

function* myGenerator() {yield "Hello";yield "World";
}const gen = myGenerator();console.log(gen.next().value); // 'Hello'
console.log(gen.next().value); // 'World'
console.log(gen.next().done);  // true

4.?yield*?表達式

yield* 用于委托給另一個生成器或可迭代對象(如數組、字符串等)。它允許在一個生成器函數中調用另一個生成器函數。

function* generator1() {yield 1;yield 2;
}function* generator2() {yield* generator1(); // 委托給 generator1yield 3;
}const gen = generator2();console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().done); // true

5.?生成器函數的特性

5.1.?惰性求值

生成器函數是惰性的,只有在調用?next()?時才會執行。這使得生成器非常適合處理大量數據或無限序列。

function* infiniteSequence() {let i = 0;while (true) {yield i++;}
}const gen = infiniteSequence();console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
// 可以無限調用

5.2.?雙向通信

生成器函數不僅可以通過 yield 返回值,還可以通過 next() 方法接收外部傳入的值。

function* generator() {const x = yield "Hello";yield x;
}const gen = generator();console.log(gen.next().value); // 'Hello'
console.log(gen.next(42).value); // 42

第一次調用 next() 時,生成器函數執行到 yield 'Hello' 并暫停。

第二次調用 next(42) 時,42 會作為 yield 表達式的值傳入,生成器函數繼續執行。

5.3. 提前終止

生成器對象提供了?return()?和?throw()?方法,可以提前終止生成器函數的執行。

return(value):終止生成器函數并返回指定的值。

throw(error):在生成器函數內部拋出一個錯誤。

function* generator() {yield 1;yield 2;yield 3;
}const gen = generator();console.log(gen.next().value); // 1
console.log(gen.return(42).value); // 42
console.log(gen.next().done); // true

6. 生成器函數的應用場景

6.1.?惰性求值

生成器函數非常適合處理大量數據或無限序列,因為它只在需要時生成值。

function* fibonacci() {let [prev, curr] = [0, 1];while (true) {yield curr;[prev, curr] = [curr, prev + curr];}
}const fib = fibonacci();console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3
console.log(fib.next().value); // 5

6.2.?異步編程

在 async/await 出現之前,生成器函數常用于簡化異步編程。通過結合 Promise 和生成器,可以實現類似于 async/await 的效果。

function* asyncGenerator() {const result1 = yield new Promise((resolve) =>setTimeout(() => resolve(1), 1000));const result2 = yield new Promise((resolve) =>setTimeout(() => resolve(2), 1000));return result1 + result2;
}function runGenerator(generator) {const gen = generator();function handle(result) {if (result.done) return Promise.resolve(result.value);return Promise.resolve(result.value).then((res) => {return handle(gen.next(res));});}return handle(gen.next());
}runGenerator(asyncGenerator).then(console.log); // 3

6.3.?自定義迭代器

生成器函數可以用于創建自定義迭代器,簡化迭代器的實現。

const myIterable = {*[Symbol.iterator]() {yield 1;yield 2;yield 3;},
};for (const value of myIterable) {console.log(value); // 1, 2, 3
}

7. 總結

1. 生成器函數使用 function* 定義,通過 yield 暫停和恢復執行;

2. 生成器函數返回一個生成器對象,該對象是一個迭代器,可以通過 next() 方法逐步執行;

3. yield* 用于委托給另一個生成器或可迭代對象;

4. 生成器函數適用于惰性求值、異步編程和自定義迭代器等場景;

生成器函數提供了一種強大的控制流機制,使得你可以更靈活地管理函數的執行過程。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/72924.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/72924.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/72924.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

計算機網絡——交換機

一、什么是交換機? 交換機(Switch)是局域網(LAN)中的核心設備,負責在 數據鏈路層(OSI第二層)高效轉發數據幀。它像一位“智能交通警察”,根據設備的 MAC地址 精準引導數…

Git合并工具在開發中的使用指南

在團隊協作開發中,Git 是最常用的版本控制工具,而代碼合并(Merge)是多人協作不可避免的環節。當多個開發者同時修改同一文件的相同區域時,Git 無法自動完成合并,此時需要借助合并工具(Merge Too…

實現多語言適配

1.在res下創建多語言資源文件: 2.選擇需要的語言 然后得到多種語言適配string文件: 3.代碼設置多語言 object LanguageHelper {/*** 獲取適配的 Context*/fun getAttachBaseContext(context: Context): Context {return if (Build.VERSION.SDK_INT > …

【學習方法一】

學習方法一 一、通用高效學習法二、學科專項方法三、工具與技術輔助四、習慣與心理策略五、避免常見誤區總結六、進階學習策略七、解決學習痛點八、場景化學習法九、資源與工具推薦十、個性化學習調整十一、長期學習心態十二、常見問題QA十三、應對特殊挑戰的學習法十四、健康與…

Golang學習筆記_44——命令模式

Golang學習筆記_41——觀察者模式 Golang學習筆記_42——迭代器模式 Golang學習筆記_43——責任鏈模式 文章目錄 一、核心概念1. 定義2. 解決的問題3. 核心角色4. 類圖 二、特點分析三、適用場景1. 事務管理系統2. 多媒體遙控器3. 操作審計系統 四、Go語言實現示例五、高級應用…

應急響應--流量分析

(一)Cobalt Strike流量特征分析 1.HTTP特征 源碼特征: 在流量中,通過http協議的url路徑,在checksum8解密算法計算后,32位的后門得到的結果是92,64位的后門得到的結果是93,該特征符…

CI/CD—Jenkins配置一次完整的jar自動化發布流程

背景: 實現設想: 要創建自動化發布,需要準備一臺測試服務器提前安裝好java運行所需的環境,JDK版本最好和Windows開發機器上的版本一致,在Jenkins上配置將構建好的jar上傳到測試服務器上,測試服務器自動啟動…

創建分區表ORA-14037

1、故障現象 在跑腳本的時候創建物化試圖提示分區界限過高 2、解決方法 最終原因是:缺少了 這個 r34411分區,加上就好。 判斷是物化視圖創建的時候需要兼容所有分區的數據,所以報錯,而分區表則不存在這種情況 3、測試驗證 分區…

轉和git subtree管理方式為git submodule的管理方式

將 Git 子樹(subtree)轉換為子模塊(submodule)的步驟如下: 1. 確定子樹的路徑和對應的遠程倉庫地址 找到當前項目中子樹的路徑以及對應的遠程倉庫地址。例如,假設子樹的路徑為 subtree-folder&#xff0c…

基于51單片機多功能防盜報警系統

基于51單片機多功能防盜報警系統( proteus仿真程序設計報告原理圖講解視頻) 1. 主要功能:2. 講解視頻:3. 仿真4. 程序代碼5. 設計報告6. 原理圖7. 設計資料內容清單&&下載鏈接 仿真圖proteus8.9及以上 程序編譯器:keil 4/…

R語言和RStudio安裝

整體還是比較簡單的,主要是記錄個流程。 官方鏡像站列表R語言官網 1 安裝R(2025/3/6) R語言官網:The R Project for Statistical Computing 打開之后就Hello world一下吧 配置環境變量 2 安裝RStudio 下載地址:htt…

Ubuntu 22.04 升級到 Ubuntu 24.04 全流程指南

📌 1. 前言 Ubuntu 24.04 是最新的 LTS 版本,帶來了內核更新、性能優化以及更強的安全性。本指南詳細記錄了從 Ubuntu 22.04 升級到 24.04 的完整過程,包括 升級前的準備、遇到的問題及如何選擇最佳選項,避免升級失敗或系統損壞。…

【每日學點HarmonyOS Next知識】Web跨域資源、Web長按菜單、Web攔截請求、禁止錄屏、Base64圖片寬高

1、HarmonyOS Web組件本地資源跨域問題? 關于資源跨域問題的解決,可以參考以下官網文檔:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/web-cross-origin-V5 方法一 為了使Web組件能夠成功訪問跨域資源,開…

數據庫查問題常用OS命令匯總

1、內存使用情況查看 top //查看活躍進程占用情況 free -mh //查看操作系統當前可用內存 2、cpu使用情況 lscpu //查看os cpu情況 sar -u -f sar文件名 -s hh:mm:ss -e hh:mm:ss //查看對應日期的歷史cpu情況 top //查看當前活躍進程使用cpu情況 3、io情況 iostat …

nlp培訓重點-5

1. LoRA微調 loader: # -*- coding: utf-8 -*-import json import re import os import torch import numpy as np from torch.utils.data import Dataset, DataLoader from transformers import BertTokenizer """ 數據加載 """cl…

CI/CD—Jenkins配置Maven+GitLab自動構建jar包

一、安裝Maven插件通過Maven構建項目 1、在Jenkins上安裝Maven Integration plugin插件 2、創建一個maven項目 2.1、填寫構建的名稱和描述等 2.2、填寫連接git的url 報錯:無法連接倉庫:Error performing git command: git ls-remote -h http://192.168.…

ngx_regex_create_conf

ngx_regex_create_conf 定義在 src/core/ngx_regex.c static void * ngx_regex_create_conf(ngx_cycle_t *cycle) {ngx_regex_conf_t *rcf;ngx_pool_cleanup_t *cln;rcf ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));if (rcf NULL) {return NULL;}rcf->p…

【數據結構】初識集合框架及背后的數據結構(簡單了解)

目錄 前言 如何學好數據結構 1. 什么是集合框架 2. 集合框架的重要性 3. 背后所涉及的數據結構以及算法 3.1 什么是數據結構 3.2 容器背后對應的數據結構 3.3 相關java知識 3.4 什么是算法 3.5 基本關系說明(重要,簡單了解) 前言 …

P9242 [藍橋杯 2023 省 B] 接龍數列--DP【巧妙解決接龍問題】

P9242 [藍橋杯 2023 省 B] 接龍數列--DP 題目 解析什么時候該用 DP?動態規劃 vs 其他方法代碼 題目 解析 這題沒思路,壓根沒想到DP 😦 看了大神的題解,利用dp記錄每一個數結尾的長度,最后再用N-dp中的最大值&#xf…

用《設計模式》的角度優化 “枚舉”

枚舉應該都有用過,枚舉主要的作用是為了方便用戶查找和引用枚舉。 案例一 下面的枚舉邏輯很簡單,就是通過枚舉值返回不同的結果。 public enum OperationEnum {EQUAL_TO,CONTAINS,START_WITH,END_WITH;public String getOperationValue(String value)…