📋 目錄
這是 TC39 新語法深度解析系列的第五篇。過去,迭代器(Iterator)是 JavaScript 中「感覺應該很強大但實際上很少用」的物件——因為它沒有
map、filter、take這些常見方法。Iterator Helpers 改變了這一切。
過去的痛:迭代器有力量,但沒有工具
// 迭代器可以懒惰地處理數據(不需要先把所有數據放進記憶體)
// 但過去它沒有任何實用的方法...
const largeData = generateLargeDataset(); // 一百萬筆
const iterator = largeData[Symbol.iterator]();
// 想做這種事情?需要手動實現
function* map(iter, fn) {
for (const item of iter) {
yield fn(item);
}
}
// Iterator Helpers 讓這一切變成原生方法
新方法速覽
// 十個新方法
iterator.map(fn) // 映射
iterator.filter(fn) // 過濾
iterator.take(n) // 取前 n 個
iterator.drop(n) // 跳過前 n 個
iterator.flatMap(fn) // 展平 + 映射
iterator.reduce(fn, init) // 聚合
iterator.toArray() // 轉成陣列
iterator.forEach(fn) // 遍歷(副作用)
iterator.every(fn) // 全都滿足?
iterator.some(fn) // 有一個滿足?
iterator.find(fn) // 找到第一個滿足的
take():處理大數據集
// 處理超大型資料時,只取需要的部分
function* generateFibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
// 只取前 20 個——不需要計算到一百萬
const first20 = generateFibonacci()
.take(20)
.toArray();
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
map + filter 組合:Lazy 流水線
// 過去:陣列方法會立刻創建中間陣列
const result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.filter(x => x % 2 === 0) // 創建新陣列
.map(x => x * 2); // 再創建一個
// Iterator Helpers:沒有中間陣列——每個元素通過每個步驟後才到下一步
function* oddsAndSquares(n) {
yield* n
.filter(x => x % 2 !== 0) // 一個一個處理
.map(x => x * x); // 沒有中間陣列
}
const result = [...oddsAndSquares([1, 2, 3, 4, 5])];
// [1, 9, 25]
實際應用:分頁 API 的懶惰處理
// 模擬分頁 API(一次拿 100 筆)
async function* fetchAllPages() {
let page = 1;
while (true) {
const data = await fetch(`/api/items?page=${page}&limit=100`).then(r => r.json());
if (data.length === 0) break;
yield* data;
page++;
}
}
// 只取前 10 筆——實際上只會發送一個請求
const first10 = await fetchAllPages()
.take(10)
.toArray();
這個模式在處理分頁或大資料集時特別有價值——不需要把所有資料都載入記憶體,就可以在第一時間只取需要的部分。
Iterator.from():把任何可迭代物件轉成迭代器
const arr = [1, 2, 3];
const iter = Iterator.from(arr);
const doubled = iter.map(x => x * 2).toArray();
// [2, 4, 6]
與 Array 方法的比較
| 場景 | Array 方法 | Iterator 方法 |
|---|---|---|
| 大資料集 | ❌ 需要全部載入記憶體 | ✅ 懶惰處理 |
| 多次轉換 | ❌ 每步創建中間陣列 | ✅ 一個元素通過每步 |
| 無限序列 | ❌ 不可能 | ✅ take() 自動終止 |
| 回頭遍歷 | ✅ 可以多次迭代 | ❌ 只能一次 |
瀏覽器支援
所有主流瀏覽器 2024 版本(Chrome 122+、Firefox 127+、Safari 17.4+)都已支援。可以直接使用。
總結
Iterator Helpers 讓 JavaScript 的 Iterator 從「理論上存在」變成「實務上可用」:
// 從此告別手動實現 map/filter on iterator
function* map(iter, fn) {
for (const item of iter) yield fn(item);
}
// 直接用原生語法
const result = Iterator.from(data).map(fn).filter(fn2).take(10).toArray();
這是 TC39 新語法深度解析系列的第五篇。下一篇:裝飾器語法正式標準化 — Decorators。
延伸閱讀
- TypeScript 6.0 RC 升級指南 — 支援 Iterator Helpers 新語法
本文基於 TC39 Iterator Helpers 提案(Stage 4)整理。