JavaScript 是一種以其多功能性和易用性而聞名的語言,它具有多種功能,對於新手和經驗豐富的開發人員來說都非常強大。其中一項功能就是生成器。 ECMAScript 2015 (ES6) 中引入的生成器提供了一種處理迭代和非同步程式設計的獨特方法。在本文中,我們將探討什麼是生成器、它們如何運作以及它們的實際應用。


什麼是 generator?

生成器是一種特殊類型的函數,可以暫停和恢復執行。與呼叫時執行完成的常規函數不同,生成器在指定點將控制權交還給呼叫者。這種暫停和恢復的能力使它們對於需要一系列值或需要更優雅地處理非同步操作的任務特別有用。


文法和基本用法

生成器函數是使用function*語法定義的,並使用yield關鍵字來暫停執行。

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

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 }

在此範例中, myGenerator是產生三個值的生成器函數。 gen物件是透過呼叫生成器函數所建立的迭代器。呼叫gen.next()傳回一個具有兩個屬性的物件: value (產生的值)和done (一個布林值,指示生成器是否已完成)。


yield的力量

yield關鍵字不僅暫停產生器,還允許將值傳回產生器。

function* countingGenerator() {
  let count = 0;
  while (true) {
    count = yield count + 1;
  }
}

const counter = countingGenerator();

console.log(counter.next()); // { value: 1, done: false }
console.log(counter.next(10)); // { value: 11, done: false }
console.log(counter.next(20)); // { value: 21, done: false }

在這裡,每次呼叫counter.next()都會恢復生成器,並且可以傳遞一個值來替換變數count 。這演示了生成器如何在暫停期間維護和更新其狀態。


實際應用

📌 迭代

生成器在需要自訂迭代邏輯的場景中大放異彩。例如,您可以建立一個生成器來迭代一系列數字甚至複雜的資料結構。

function* range(start, end) {
  for (let i = start; i <= end; i++) {
    yield i;
  }
}

for (const num of range(1, 5)) {
  console.log(num); // 1, 2, 3, 4, 5
}

📌 非同步編程

生成器與 Promise 結合可以簡化非同步程式碼。像co這樣的函式庫使用這種模式比嵌套回呼或承諾鏈更自然地管理非同步流。

const fetch = require('node-fetch');

function* fetchData(url) {
  const response = yield fetch(url);
  const data = yield response.json();
  return data;
}

const co = require('co');

co(fetchData, 'https://api.example.com/data')
  .then(data => console.log(data))
  .catch(err => console.error(err));

📌 無限序列

生成器可以建立無限序列,而由於陣列的有限性,這是不可能的。這在模擬、資料流或任何需要無限系列值的場景中非常有用。

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

結論

JavaScript 中的生成器提供了一個強大的機制來處理序列、管理函數呼叫之間的狀態以及簡化非同步程式碼。

它們在 ES6 中的引入為該語言增添了顯著的靈活性和強大功能,使複雜的迭代和非同步模式變得更加平易近人。

隨著您深入研究 JavaScript,掌握生成器可以增強您編寫高效且可維護程式碼的能力。無論您是處理資料流、自訂迭代器還是非同步操作,生成器都提供了一個強大的工具來提升您的程式設計工具包。


快樂編碼! 🔥

領英

X(推特)

電報

Youtube

不和諧

Facebook

Instagram


原文出處:https://dev.to/alisamirali/mastering-javascript-generators-15g3


共有 0 則留言