首頁 > web前端 > js教程 > ES6發電機和迭代器:開發人員指南

ES6發電機和迭代器:開發人員指南

Christopher Nolan
發布: 2025-02-15 11:42:13
原創
879 人瀏覽過

ES6 Generators and Iterators: a Developer’s Guide

ES6為JavaScript語言引入了許多新特性。其中兩個特性,生成器和迭代器,極大地改變了我們在更複雜的前端代碼中編寫特定函數的方式。

雖然它們可以很好地協同工作,但它們實際的功能可能有點令人困惑,所以讓我們來仔細研究一下。

關鍵要點

  • ES6提供了一種更簡潔的for循環編寫方式,提供了一種更類似Python的方式來直接與數據集中的元素交互,使代碼更易於閱讀和編寫。
  • ES6中的生成器是記住每次調用之間狀態的函數。它們每次被調用時都可以生成序列中的下一個值,有效地創建自定義迭代。
  • 生成器函數中的“yield”關鍵字類似於“return”,但它保持函數的狀態,允許它在下一次調用時從中斷處繼續執行。
  • 雖然Node和現代瀏覽器支持ES6特性,但舊版瀏覽器可能需要Babel等轉譯器將ES6代碼轉換為ECMAScript 5代碼。

迭代器

迭代是編程中常見的做法,通常用於循環遍歷一組值,轉換每個值,或以某種方式使用或保存它以備後用。

在JavaScript中,我們一直都有這樣的for循環:

for (var i = 0; i < foo.length; i++) {
  // 对i执行某些操作
}
登入後複製
登入後複製
登入後複製

但ES6給了我們另一種選擇:

for (const i of foo) {
  // 对i执行某些操作
}
登入後複製
登入後複製

這可以說是更簡潔、更容易使用,讓我想起了Python和Ruby等語言。但是,關於這種新型迭代,還有一點非常重要需要注意:它允許您直接與數據集的元素交互。

假設我們想找出數組中的每個數字是否為素數。我們可以通過創建一個執行此操作的函數來做到這一點。它可能看起來像這樣:

function isPrime(number) {
  if (number <= 1) {
    return false;
  } else if (number === 2) {
    return true;
  }

  for (var i = 2; i < number; i++) {
    if (number % i === 0) {
      return false;
      break;
    }
  }

  return true;
}
登入後複製
登入後複製

不是世界上最好的,但它有效。下一步是循環遍歷我們的數字列表,並使用我們閃亮的新函數檢查每個數字是否為素數。這很簡單:

var possiblePrimes = [73, 6, 90, 19, 15];
var confirmedPrimes = [];

for (var i = 0; i < possiblePrimes.length; i++) {
  if (isPrime(possiblePrimes[i])) {
    confirmedPrimes.push(possiblePrimes[i]);
  }
}

// confirmedPrimes现在是[73, 19]
登入後複製
登入後複製

同樣,它有效,但它很笨拙,這種笨拙很大程度上取決於JavaScript處理for循環的方式。但是,有了ES6,我們就在新的迭代器中得到了一個幾乎類似Python的選項。因此,前面的for循環可以這樣編寫:

const possiblePrimes = [73, 6, 90, 19, 15];
const confirmedPrimes = [];

for (const i of possiblePrimes){
   if ( isPrime(i) ){
      confirmedPrimes.push(i);
   }
}

// confirmedPrimes现在是[73, 19]
登入後複製

這要乾淨得多,但最引人注目的是for循環。變量i現在代表名為possiblePrimes的數組中的實際項。因此,我們不再需要按索引調用它了。這意味著我們不必在循環中調用possiblePrimes[i],而只需調用i即可。

在幕後,這種迭代利用了ES6閃亮的新Symbol.iterator()方法。這個方法負責描述迭代,並且在被調用時,返回一個JavaScript對象,其中包含循環中的下一個值和一個done鍵,該鍵根據循環是否完成而為true或false。

如果您對這種細節感興趣,您可以閱讀Jake Archibald撰寫的這篇精彩博文《Iterators gonna iterate》。當我們深入探討本文的另一部分:生成器時,它也會讓您很好地了解幕後發生了什麼。

生成器

生成器(也稱為“迭代器工廠”)是一種新型的JavaScript函數,用於創建特定的迭代。它們為您提供了特殊、自定義的循環遍歷內容的方式。

好的,那麼這一切意味著什麼?讓我們來看一個例子。假設我們想要一個函數,每次調用它時都會給我們下一個素數:

for (var i = 0; i < foo.length; i++) {
  // 对i执行某些操作
}
登入後複製
登入後複製
登入後複製

如果您習慣使用JavaScript,其中一些內容看起來有點像巫術,但實際上它並不太糟糕。我們在關鍵字function之後有那個奇怪的星號,但這只是告訴JavaScript我們正在定義一個生成器。

另一個奇怪的部分是yield關鍵字。這實際上是生成器在您調用它時吐出的內容。它大致相當於return,但它保留了函數的狀態,而不是在每次調用它時都重新運行所有內容。它在運行時“記住”它的位置,因此下次您調用它時,它會從中斷處繼續執行。

這意味著我們可以這樣做:

for (const i of foo) {
  // 对i执行某些操作
}
登入後複製
登入後複製

然後,每當我們想要獲得——你猜對了——下一個素數時,都可以調用nextPrime:

function isPrime(number) {
  if (number <= 1) {
    return false;
  } else if (number === 2) {
    return true;
  }

  for (var i = 2; i < number; i++) {
    if (number % i === 0) {
      return false;
      break;
    }
  }

  return true;
}
登入後複製
登入後複製

您也可以只調用nextPrime.next(),這在您的生成器不是無限的情況下很有用,因為它返回一個這樣的對象:

var possiblePrimes = [73, 6, 90, 19, 15];
var confirmedPrimes = [];

for (var i = 0; i < possiblePrimes.length; i++) {
  if (isPrime(possiblePrimes[i])) {
    confirmedPrimes.push(possiblePrimes[i]);
  }
}

// confirmedPrimes现在是[73, 19]
登入後複製
登入後複製

在這裡,done鍵告訴您函數是否已完成其任務。在我們的例子中,我們的函數永遠不會結束,理論上可以為我們提供所有直到無窮大的素數(如果我們有那麼多的計算機內存的話)。

很酷,那麼我現在可以使用生成器和迭代器了嗎?

儘管ECMAScript 2015已經完成,並且已經存在多年了,但其特性(特別是生成器)的瀏覽器支持遠未完善。如果您真的想使用這些和其他現代特性,您可以查看Babel和Traceur等轉譯器,它們會將您的ECMAScript 2015代碼轉換為等效的(如果可能)ECMAScript 5代碼。

還有許多在線編輯器支持ECMAScript 2015,或者專門關注它,特別是Facebook的Regenerator和JS Bin。如果您只是想玩玩並了解JavaScript現在如何編寫,那麼這些值得一看。

結論

生成器和迭代器為我們處理JavaScript問題的方法提供了相當多的新靈活性。迭代器允許我們以更類似Python的方式編寫for循環,這意味著我們的代碼看起來更簡潔,更容易閱讀。

生成器函數使我們能夠編寫記住上次看到它們的位置的函數,並且可以從中斷處繼續執行。它們在實際記住的內容方面也可以是無限的,這在某些情況下非常方便。

對這些生成器和迭代器的支持很好。它們在Node和所有現代瀏覽器中都受支持,Internet Explorer除外。如果您需要支持舊版瀏覽器,最好的辦法是使用Babel等轉譯器。

關於ECMAScript 2015生成器和迭代器的常見問題解答 (FAQ)

ECMAScript 2015中的迭代器和生成器有什麼區別?

迭代器和生成器都是ECMAScript 2015的特性,用於處理數據流。迭代器是一個對象,允許程序員遍歷集合中的所有元素。它有一個next()方法,返回序列中的下一個項目。另一方面,生成器是一個可以中途停止然後從停止處繼續的函數。換句話說,生成器看起來像一個函數,但它的行為像一個迭代器。

如何在ECMAScript 2015中使用yield關鍵字?

yield關鍵字用於ECMAScript 2015暫停和恢復生成器函數(function*或舊版生成器函數)。 yield可以從生成器函數返回一個值。這個返回值通常是一個具有兩個屬性的對象:value和done。 value屬性是計算yield表達式的結果,done是一個布爾值,指示生成器是否已生成其最後一個值。

ECMAScript 2015中next()方法的目的是什麼?

next()方法是ECMAScript 2015中迭代器協議的關鍵部分。它返回一個具有兩個屬性的對象:value和done。 value屬性是迭代序列中的下一個值,done是一個布爾值,指示迭代是否完成。如果done為true,則迭代器已超出迭代序列的末尾。

如何在ECMAScript 2015中使用生成器進行異步編程?

ECMAScript 2015中的生成器可用於簡化異步編程。它們可用於阻止執行以等待異步操作完成,而不會阻塞整個程序。這可以使異步代碼看起來和行為更像同步代碼,這更容易理解和推理。

ECMAScript 2015中for…of循環和for…in循環有什麼區別?

ECMAScript 2015中的for…of循環用於循環遍歷可迭代對象,例如數組、字符串、映射、集合等等。它使用語句調用自定義迭代鉤子,這些語句將為每個不同屬性的值執行。另一方面,for…in循環用於循環遍歷對象的屬性。它返回正在迭代的對象的鍵列表。

如何在ECMAScript 2015中創建自定義迭代器?

在ECMAScript 2015中,您可以通過定義一個具有next()方法的對象來創建自定義迭代器。此方法應返回一個具有兩個屬性的對象:value和done。 value屬性是迭代序列中的下一個值,done是一個布爾值,指示迭代是否完成。

Symbol.iterator在ECMAScript 2015中的作用是什麼?

Symbol.iterator是ECMAScript 2015中一個特殊的內置符號。它用於指定對象的默認迭代器。當需要迭代一個對象時(例如在for…of循環的開頭),它的@@iterator方法將不帶任何參數被調用,並且返回的迭代器將用於獲取要迭代的值。

你能提供ECMAScript 2015中生成器函數的示例嗎?

當然,這是ECMAScript 2015中生成器函數的一個簡單示例:

for (var i = 0; i < foo.length; i++) {
  // 对i执行某些操作
}
登入後複製
登入後複製
登入後複製

在這個例子中,idMaker函數是一個生成器,它產生一個數字序列。

如何在ECMAScript 2015中使用throw()方法和生成器?

ECMAScript 2015中的throw()方法可用於生成器,以恢復生成器函數的執行並從yield表達式拋出錯誤。 throw()方法可用於處理生成器函數執行期間發生的錯誤。

done屬性在ECMAScript 2015迭代器中的意義是什麼?

done屬性是一個布爾值,由ECMAScript 2015中的迭代器返回。它指示迭代器是否還有更多值要返回。如果done為true,則迭代器已超出迭代序列的末尾。如果done為false,則迭代器仍然可以生成更多值。

以上是ES6發電機和迭代器:開發人員指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板