可迭代物件 (Iterables)
如果一個物件實現了 Symbol.iterator 屬性,則該物件被認為是可迭代的。一些內建型別,如 Array、Map、Set、String、Int32Array、Uint32Array 等,都已經實現了它們的 Symbol.iterator 屬性。物件上的 Symbol.iterator 函式負責返回可供迭代的值列表。
Iterable 介面
如果我們想要接收上述可迭代的型別,可以使用 Iterable 型別。以下是一個示例:
tsfunction toArray<X>(xs: Iterable<X>): X[] {return [...xs]}
for..of 語句
for..of 迴圈遍歷可迭代物件,並呼叫該物件上的 Symbol.iterator 屬性。以下是一個簡單的陣列 for..of 迴圈示例:
tslet someArray = [1, "string", false];for (let entry of someArray) {console.log(entry); // 1, "string", false}
for..of 與 for..in 語句
for..of 和 for..in 語句都用於遍歷列表;但它們迭代的值不同:for..in 返回被迭代物件上的鍵列表,而 for..of 則返回被迭代物件數值屬性的值列表。
以下是一個展示這種區別的示例:
tslet list = [4, 5, 6];for (let i in list) {console.log(i); // "0", "1", "2",}for (let i of list) {console.log(i); // 4, 5, 6}
另一個區別是 for..in 可以操作任何物件;它可以用作檢查物件屬性的一種方式。而 for..of 主要關注可迭代物件的值。像 Map 和 Set 這樣的內建物件實現了 Symbol.iterator 屬性,從而允許訪問其中儲存的值。
tslet pets = new Set(["Cat", "Dog", "Hamster"]);pets["species"] = "mammals";for (let pet in pets) {console.log(pet); // "species"}for (let pet of pets) {console.log(pet); // "Cat", "Dog", "Hamster"}
程式碼生成
面向 ES5
當面向相容 ES5 的引擎時,迭代器僅允許用於 Array 型別的值。在非陣列值上使用 for..of 迴圈屬於錯誤,即使這些非陣列值實現了 Symbol.iterator 屬性。
編譯器會為 for..of 迴圈生成一個簡單的 for 迴圈,例如:
tslet numbers = [1, 2, 3];for (let num of numbers) {console.log(num);}
將被生成為:
jsvar numbers = [1, 2, 3];for (var _i = 0; _i < numbers.length; _i++) {var num = numbers[_i];console.log(num);}
面向 ECMAScript 2015 及更高版本
當面向相容 ECMAScript 2015 的引擎時,編譯器將生成 for..of 迴圈,以利用引擎中內建的迭代器實現。