JavaScript 无原生数组流类型,但可用生成器函数模拟惰性求值、按需计算的流式处理;支持 map/filter/take 等链式操作,结合可迭代协议与 async generator 实现同步/异步内存友好遍历。

JavaScript 中没有原生的“数组流(Array Stream)”类型,但可以用 stream 思想 —— 即惰性求值、按需计算、链式处理、内存友好 —— 来模拟流式遍历数组。核心是避免一次性生成全部中间结果,而是让每一步只在需要时才产出下一个值。
用生成器(Generator)实现惰性管道
生成器函数天然支持暂停/恢复执行,是实现流式处理最自然的方式。你可以把 map、filter、take 等操作封装成可组合的生成器函数:
function* map(iter, fn) {
for (const item of iter) yield fn(item);
}
<p>function* filter(iter, predicate) {
for (const item of iter) if (predicate(item)) yield item;
}</p><p>function* take(iter, n) {
let count = 0;
for (const item of iter) {
if (count >= n) break;
yield item;
count++;
}
}</p><p>// 使用示例:100万元素数组,只取前5个偶数的平方
const bigArray = Array.from({ length: 1_000<em>000 }, (</em>, i) => i);
const result = [...take(map(filter(bigArray, x => x % 2 === 0), x => x ** 2), 5)];
// → [0, 4, 16, 36, 64],全程只遍历前 ~10 个原始元素,不构建中间数组
</p>用可迭代对象 + Symbol.iterator 封装流式链
进一步封装成类,支持链式调用(类似 RxJS 或 Lodash/fp 的风格),但保持惰性:
class ArrayStream {
constructor(iterable) {
this.iterable = iterable;
}
<p>map(fn) {
return new ArrayStream(function*() {
for (const item of this.iterable) yield fn(item);
}.bind(this));
}</p><p>filter(predicate) {
return new ArrayStream(function*() {
for (const item of this.iterable) if (predicate(item)) yield item;
}.bind(this));
}</p><p>take(n) {
return new ArrayStream(function*() {
let count = 0;
for (const item of this.iterable) {
if (count >= n) break;
yield item;
count++;
}
}.bind(this));
}</p><p>toArray() {
return Array.from(this.iterable);
}
}</p><p>// 链式使用
const stream = new ArrayStream([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
.filter(x => x % 2 === 0)
.map(x => x * x)
.take(3);</p><p>console.log(stream.toArray()); // [4, 16, 36]
</p>与 async/await 结合处理异步数据流
若数组元素是 Promise 或需异步转换(如 fetch 某批 ID),可用 async generator 实现异步流式处理,避免 Promise.all 内存爆炸:
User${id}注意边界:何时不适合“流式”
流式不是银弹。以下情况需谨慎或放弃流式设计:
- 需要随机访问(如 arr[5]、arr.length)—— 生成器不可逆、无长度
- 必须保证所有元素都被处理(如日志上报、副作用累积)—— 流可能被提前中断
- 操作本身依赖全局状态(如 reduce 累加)—— 需显式传入初始值并返回新累加器,不能直接用原生 reduce
- 调试困难 —— 堆栈浅、无法断点逐行看中间数组,建议开发期搭配 .toArray() 快速验证逻辑











