ES6為JavaScript語言引入了許多新特性。其中兩個特性,生成器和迭代器,極大地改變了我們在更複雜的前端代碼中編寫特定函數的方式。
雖然它們可以很好地協同工作,但它們實際的功能可能有點令人困惑,所以讓我們來仔細研究一下。
迭代是編程中常見的做法,通常用於循環遍歷一組值,轉換每個值,或以某種方式使用或保存它以備後用。
在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的特性,用於處理數據流。迭代器是一個對象,允許程序員遍歷集合中的所有元素。它有一個next()方法,返回序列中的下一個項目。另一方面,生成器是一個可以中途停止然後從停止處繼續的函數。換句話說,生成器看起來像一個函數,但它的行為像一個迭代器。
yield關鍵字用於ECMAScript 2015暫停和恢復生成器函數(function*或舊版生成器函數)。 yield可以從生成器函數返回一個值。這個返回值通常是一個具有兩個屬性的對象:value和done。 value屬性是計算yield表達式的結果,done是一個布爾值,指示生成器是否已生成其最後一個值。
next()方法是ECMAScript 2015中迭代器協議的關鍵部分。它返回一個具有兩個屬性的對象:value和done。 value屬性是迭代序列中的下一個值,done是一個布爾值,指示迭代是否完成。如果done為true,則迭代器已超出迭代序列的末尾。
ECMAScript 2015中的生成器可用於簡化異步編程。它們可用於阻止執行以等待異步操作完成,而不會阻塞整個程序。這可以使異步代碼看起來和行為更像同步代碼,這更容易理解和推理。
ECMAScript 2015中的for…of循環用於循環遍歷可迭代對象,例如數組、字符串、映射、集合等等。它使用語句調用自定義迭代鉤子,這些語句將為每個不同屬性的值執行。另一方面,for…in循環用於循環遍歷對象的屬性。它返回正在迭代的對象的鍵列表。
在ECMAScript 2015中,您可以通過定義一個具有next()方法的對象來創建自定義迭代器。此方法應返回一個具有兩個屬性的對象:value和done。 value屬性是迭代序列中的下一個值,done是一個布爾值,指示迭代是否完成。
Symbol.iterator是ECMAScript 2015中一個特殊的內置符號。它用於指定對象的默認迭代器。當需要迭代一個對象時(例如在for…of循環的開頭),它的@@iterator方法將不帶任何參數被調用,並且返回的迭代器將用於獲取要迭代的值。
當然,這是ECMAScript 2015中生成器函數的一個簡單示例:
for (var i = 0; i < foo.length; i++) { // 对i执行某些操作 }
在這個例子中,idMaker函數是一個生成器,它產生一個數字序列。
ECMAScript 2015中的throw()方法可用於生成器,以恢復生成器函數的執行並從yield表達式拋出錯誤。 throw()方法可用於處理生成器函數執行期間發生的錯誤。
done屬性是一個布爾值,由ECMAScript 2015中的迭代器返回。它指示迭代器是否還有更多值要返回。如果done為true,則迭代器已超出迭代序列的末尾。如果done為false,則迭代器仍然可以生成更多值。
以上是ES6發電機和迭代器:開發人員指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!