Iterator helpers في JavaScript: map و filter و take على أي iterator من غير spread

map و filter و take و toArray بقوا على أي iterator (generators و Map و Set) — شغل lazy من غير مصفوفات وسيطة. Baseline من مارس ٢٠٢٥ و Node 22.

لو عندك generator أو Map أو Set وعايز تفلتر وتحوّل وتاخد أول كام نتيجة، كان الحل المعتاد إنك تحوّلهم لمصفوفة الأول بـ [...it] وبعدين تستخدم filter و map. ده بيعمل مصفوفات وسيطة، ومع generator مالوش نهاية مش هينفع أصلًا.

من مارس ٢٠٢٥ بقى فيه Iterator helpers: methods على Iterator.prototype نفسه، يعني على أي iterator.

إيه الـ methods المتاحة؟

حسب MDN:

  • map() و filter() و flatMap(): بيرجّعوا iterator جديد (lazy)
  • take(n) و drop(n): تاخد أول n عناصر أو تتخطاهم
  • toArray() و reduce() و forEach(): بيستهلكوا الـ iterator ويرجّعوا نتيجة
  • some() و every() و find(): بيوقفوا أول ما الإجابة تبان
  • Iterator.from(): بيحوّل أي iterable أو object فيه next() لـ iterator تقدر تستخدم عليه الـ helpers

قبل وبعد

قبل:

const firstThree = [...gen()].filter(f).map(g).slice(0, 3);

ده بيقرا الـ generator كله الأول. لو مالوش نهاية، الكود هيفضل شغال.

بعد:

function* naturals() {
  let n = 1;
  while (true) yield n++;
}

naturals()
  .filter((n) => n % 2 === 0)
  .map((n) => n * n)
  .take(3)
  .toArray(); // [4, 16, 36]

كل عنصر بيعدّي على filter ثم map واحد واحد، و take(3) بيوقف السلسلة بعد ٣ نتايج.

على Map و Set كمان

keys() و values() و entries() بتاعة Map و Set بيرجّعوا iterators بتورث من Iterator.prototype، فالـ helpers شغالة عليهم على طول:

const users = new Map([["ahmed", 1], ["sara", 2], ["amr", 3]]);

users.keys().filter((k) => k.startsWith("a")).toArray(); // ["ahmed", "amr"]

خلي بالك: الـ iterator بيتستهلك مرة واحدة

const it = [1, 2, 3].values().map((x) => x * 2);
it.toArray(); // [2, 4, 6]
it.toArray(); // []

لو محتاج النتيجة أكتر من مرة، خزّنها في متغير بعد أول toArray().

الدعم

حسب بيانات التوافق على MDN، الـ feature بقت Baseline (Newly available) من ٣١ مارس ٢٠٢٥:

  • Chrome و Edge: 122
  • Firefox: 131
  • Safari: 18.4
  • Node.js: 22.0.0

على Node 20 هتاخد TypeError: ... is not a function، فاتأكد من نسخة الـ runtime في الـ backend أو الـ CI قبل ما تعتمد عليها.

رأيي

الـ helpers دي مفيدة جدًا مع الـ generators والـ streams الصغيرة، ومع Map.keys() بالذات بدل الـ spread المتكرر. للمصفوفات العادية، Array.prototype.map/filter لسه مناسبين، والفرق الحقيقي بيبان لما البيانات كبيرة أو مالهاش نهاية، أو لما محتاج أول كام نتيجة بس.

المصدر

  • JavaScript
  • Iterator
  • Baseline
  • Node.js
  • Full Stack Tips
  • WebDev