مجموعه‌ها و پیمایشگرها

Set و WeakSet، Map و WeakMap، متدهای آن‌ها، WeakRef و FinalizationRegistry، Iterator و Generator، yield، Async Generator و پیمایش ناهمگام.

Set — مجموعه مقادیر یکتا

Set مجموعه‌ای از مقادیر بدون تکرار است:

const set = new Set([1, 2, 2, 3, 3, 3]);
console.log(set);        // Set(3) {1, 2, 3}
console.log(set.size);   // 3

// افزودن — تکراری‌ها نادیده گرفته می‌شوند:
set.add(4);
set.add(4);              // بی‌اثر
console.log(set.has(4)); // true

// حذف:
set.delete(1);
console.log(set.size);   // 3

// حذف همه:
// set.clear();

کاربرد عملی Set — حذف تکراری‌ها

const numbers = [1, 2, 2, 3, 4, 4, 5];
const unique = [...new Set(numbers)];
console.log(unique); // [1, 2, 3, 4, 5]

// بررسی عضویت سریع — O(1):
const banned = new Set(["spam", "bad", "fake"]);
console.log(banned.has("spam")); // true — سریع‌تر از includes

Map — دیکشنری کلید-مقدار

Map بر خلاف Object هر نوعی را به‌عنوان کلید می‌پذیرد:

const map = new Map();

// کلیدهای مختلف — حتی Object و NaN:
map.set("name", "علی");
map.set(42, "عدد");
map.set({ id: 1 }, "شیء");
map.set(NaN, "Not a Number");

console.log(map.size);      // 4
console.log(map.get("name")); // علی
console.log(map.get(NaN));  // Not a Number — NaN هم کار می‌کند!

// زنجیره‌ای:
map.set("a", 1).set("b", 2);

// حذف:
map.delete(42);
console.log(map.has(42));   // false

پیمایش Map

const scores = new Map([
    ["علی", 18],
    ["سارا", 20],
    ["رضا", 16]
]);

// entries — پیش‌فرض:
for (const [name, score] of scores) {
    console.log(name + ": " + score);
}

// فقط کلیدها یا مقادیر:
console.log([...scores.keys()]);   // ["علی", "سارا", "رضا"]
console.log([...scores.values()]); // [18, 20, 16]
Map در برابر Object: Map ترتیب را حفظ می‌کند، اندازه (size) دارد، هر کلیدی می‌پذیرد و برای داده‌های پویا بهینه است.

WeakMap — مراجع ضعیف

کلیدها باید شیء باشند و GC می‌تواند آن‌ها را جمع کند:

const weakMap = new WeakMap();
let user = { name: "علی" };

weakMap.set(user, "داده اضافه");
console.log(weakMap.get(user)); // داده اضافه

// حالا اگر user حذف شود، داده هم خودکار آزاد می‌شود:
user = null; // — قابل بازیابی توسط GC — بدون نشتی حافظه!
WeakMap قابل پیمایش نیست و size ندارد — فقط get/set/has/delete.

WeakSet

const visited = new WeakSet();
let node1 = { id: 1 };
let node2 = { id: 2 };

// علامت‌گذاری بدون جلوگیری از GC:
visited.add(node1);
console.log(visited.has(node1)); // true
console.log(visited.has(node2)); // false

WeakRef و FinalizationRegistry

برای نگهداری ضعیف و callback پس از GC:

let target = { data: "مهم" };

// WeakRef — مرجع بدون جلوگیری از GC:
const ref = new WeakRef(target);
console.log(ref.deref()?.data); // مهم — هنوز زنده است

// FinalizationRegistry — اطلاع پس از جمع‌آوری:
const registry = new FinalizationRegistry(name => {
    console.log(name + " جمع‌آوری شد");
});
registry.register(target, "target");

target = null; // پس از GC پیام چاپ می‌شود

Iterator — پیمایشگر

هر شیء قابل پیمایش (Iterable) متد Symbol.iterator دارد که یک Iterator برمی‌گرداند:

const numbers = [10, 20, 30];
const iterator = numbers[Symbol.iterator]();

console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

ساخت Iterable سفارشی

class NumberRange {
    constructor(start, end, step = 1) {
        this.start = start;
        this.end = end;
        this.step = step;
    }

    [Symbol.iterator]() {
        let current = this.start;
        const end = this.end;
        const step = this.step;
        return {
            next() {
                if (current <= end) {
                    const value = current;
                    current += step;
                    return { value, done: false };
                }
                return { value: undefined, done: true };
            }
        };
    }
}

const range = new NumberRange(1, 10, 3);
console.log([...range]);     // [1, 4, 7, 10]
for (const n of range) console.log(n);

Generator Function — تابع مولد

با function* تعریف و با yield مقدار تولید می‌شود:

function* idGenerator() {
    let id = 1;
    while (true) {           // حلقه بی‌نهایت — بی‌خطر!
        yield id++;
    }
}

const gen = idGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
// هر بار که لازم شد مقدار بعدی — بدون محاسبه همه!

yield — تولید و دریافت مقدار

function* conversation() {
    const name = yield "اسمت چیه؟";
    yield "سلام " + name + "!";
    const mood = yield "چطوری؟";
    yield "خوشحالم که " + mood + " هستی";
}

const talk = conversation();
console.log(talk.next().value);      // اسمت چیه؟
console.log(talk.next("علی").value); // سلام علی!
console.log(talk.next().value);      // چطوری؟
console.log(talk.next("خوب").value); // خوشحالم که خوب هستی

yield* — واگذاری به Generator دیگر

function* inner() {
    yield 1;
    yield 2;
}

function* outer() {
    yield 0;
    yield* inner();   // اجرای کامل inner
    yield 3;
}

console.log([...outer()]); // [0, 1, 2, 3]

Generator برای دنباله بی‌نهایت

function* fibonacci() {
    let [a, b] = [0, 1];
    while (true) {
        yield a;
        [a, b] = [b, a + b];
    }
}

const fib = fibonacci();
// ۱۰ عدد اول:
for (let i = 0; i < 10; i++) {
    console.log(fib.next().value); // 0 1 1 2 3 5 8 13 21 34
}

Async Iterator و Async Generator

// Async Generator — تولید مقادیر ناهمگام:
async function* fetchPages(baseUrl) {
    let page = 1;
    while (page <= 3) {
        // شبیه‌سازی fetch:
        const data = await new Promise(resolve =>
            setTimeout(() => resolve("صفحه " + page++), 100)
        );
        yield data;
    }
}

// for await...of — پیمایش ناهمگام:
(async () => {
    for await (const page of fetchPages()) {
        console.log(page); // صفحه 1، صفحه 2، صفحه 3
    }
})();

جمع‌بندی

ساختارویژگیکاربرد
Setمقادیر یکتاحذف تکراری، عضویت سریع
Mapکلید هر نوعدیکشنری، کش
WeakMapکلید شیء، ضعیفمتادیتا بدون نشتی
Generatorتولید تنبلدنباله‌ها، بی‌نهایت
Async Generatorتولید ناهمگامصفحه‌بندی، استریم

این مبحث بخشی از دوره آموزش کامل جاوا اسکریپت است.

ابزارهای مرتبط