Set In JavaScript

🧠 ما هو Set في JavaScript؟

Set هو نوع خاص من الكائنات Objects يُستخدم لتخزين قيم فريدة فقط (لا تتكرر) من أي نوع: بدائي أو كائن.

✅ خصائص Set الأساسية
الخاصيةالوصف
لا يقبل القيم المكررةيتم تجاهل أي قيمة مكررة مضافة.
يحافظ على الترتيبالقيم تحفظ بنفس ترتيب الإدخال.
يقبل أنواع بيانات مختلفةيمكن إدخال أرقام، نصوص، كائنات، دوال، إلخ
📦 إنشاء Set
✅ الصيغة:
const mySet = new Set();
JavaScript
const numbers = new Set();

numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(2); // سيتم تجاهل الرقم 2 لأنه مكرر

console.log(numbers); // Set(3) {1, 2, 3}
JavaScript
🔄 دوال وخصائص Set
الدالة/الخاصيةالوظيفةمثال
add(value)يضيف قيمة إلى الـ SetmySet.add(5)
delete(value)يحذف قيمة من الـ SetmySet.delete(5)
has(value)يتحقق هل القيمة موجودةmySet.has(5)true/false
clear()يحذف كل العناصرmySet.clear()
sizeعدد العناصر في الـ SetmySet.size
🧪 أمثلة تفصيلية
🔹 1. add():
const set = new Set();
set.add('apple');
set.add('banana');
set.add('apple'); // سيتم تجاهلها

console.log(set); // Set(2) {"apple", "banana"}
JavaScript

🔹 2. has():

console.log(set.has('banana')); // true
console.log(set.has('orange')); // false
JavaScript

🔹 3. delete():

set.delete('banana');
console.log(set); // Set(1) {"apple"}
JavaScript

🔹 4. clear():

set.clear();
console.log(set); // Set(0) {}
JavaScript

🔹 5. size:

const fruits = new Set(['apple', 'banana', 'orange']);
console.log(fruits.size); // 3
JavaScript
🔁 التكرار على Set

يمكنك التكرار على Set باستخدام:

🔸 for...of:
const mySet = new Set(['a', 'b', 'c']);
for (const value of mySet) {
  console.log(value);
}
JavaScript

🔸 forEach():

mySet.forEach((value) => {
  console.log(value);
});
JavaScript

🧩 تحويل Set إلى Array

const mySet = new Set([1, 2, 3]);
const arr = Array.from(mySet);
console.log(arr); // [1, 2, 3]
JavaScript

أو باستخدام spread:

const arr2 = [...mySet];
JavaScript
📘 فوائد استخدام Set
  1. التخلص من التكرار:
const nums = [1, 2, 2, 3, 4, 4];
const unique = [...new Set(nums)];
console.log(unique); // [1, 2, 3, 4]
JavaScript

أداء أفضل في البحث (has) من المصفوفة الكبيرة.

تخزين البيانات المؤقتة أو القيم الفريدة مثل كلمات المرور المولدة أو معرفات الجلسة.

💡 مقارنات سريعة بين Set و Array
الخاصيةSetArray
القيم المكررةلا يُسمح بهايُسمح
الترتيبيحافظ عليهيحافظ عليه
البحث عن قيمةset.has() أسرعarray.includes() أبطأ
التكرارسهلسهل
الأداءأفضل للبيانات الفريدةأفضل للبيانات العادية
🧠 ملاحظات متقدمة.
🧠 العمليات على Sets (يدويًا)
🔸 الفرق (difference):
function difference(setA, setB) {
  return new Set([...setA].filter(x => !setB.has(x)));
}

const a = new Set([1, 2, 3, 4]);
const b = new Set([3, 4, 5]);

console.log(difference(a, b)); // Set(2) {1, 2}
JavaScript

🔸 التقاطع (intersection):

function intersection(setA, setB) {
  return new Set([...setA].filter(x => setB.has(x)));
}

console.log(intersection(a, b)); // Set(2) {3, 4}
JavaScript

🔸 الاتحاد (union):

function union(setA, setB) {
  return new Set([...setA, ...setB]);
}

console.log(union(a, b)); // Set(5) {1, 2, 3, 4, 5}
JavaScript

🧠 دعم الأنواع المرجعية (الكائنات)

const set = new Set();

const obj1 = { id: 1 };
const obj2 = { id: 1 };

set.add(obj1);
set.add(obj2); // لا يعتبر مكرر لأن المرجع مختلف

console.log(set.size); // 2
JavaScript
🔚 الخلاصة
الميزةالتقييم
إزالة التكرار✅ ممتازة
أداء عند البحث✅ سريع
دعم أنواع متعددة
سهولة التحويل إلى Array
1. WeakSet (مجموعة ضعيفة)
✅ ما هو؟

WeakSet هو نوع خاص من الكائنات في JavaScript يشبه Set، لكنه يأتي بقيود وخصائص مختلفة تجعله مفيدًا في حالات معينة، خصوصًا عند التعامل مع الكائنات (objects) فقط.

🔍 الفرق الأساسي بين Set و WeakSet

الخاصيةSetWeakSet
يدعم جميع أنواع القيم✅ نعم❌ لا، فقط الكائنات (objects)
يمكن التكرار عليه✅ نعم (forEach, for...of)❌ لا يمكن التكرار عليه
قابل للإزالة التلقائية من الذاكرة❌ لا✅ نعم (garbage collected تلقائيًا)
يدعم .size✅ نعم❌ لا
يدعم .clear()✅ نعم❌ لا
  • يخزن فقط الكائنات (ولا يقبل القيم البدائية مثل أرقام أو نصوص).
  • لا يمكن الوصول إلى حجمه (لا يوجد .size).
  • لا يمكن التكرار عليه.
  • لا يمنع جمع القمامة (garbage collection) من إزالة الكائنات غير المستخدمة.
✅ الاستخدام:
const ws = new WeakSet();

const obj = { name: "Yasin" };

ws.add(obj);
console.log(ws.has(obj)); // true

ws.delete(obj);
console.log(ws.has(obj)); // false
JavaScript
const ws = new WeakSet();

const obj1 = { name: "Ali" };
const obj2 = { name: "Sara" };

ws.add(obj1);
ws.add(obj2);

console.log(ws.has(obj1)); // true

ws.delete(obj1);
console.log(ws.has(obj1)); // false
JavaScript

⚠️ القيود:

لا يقبل القيم البدائية:

ws.add(1); // ❌ TypeError
JavaScript

لا يمكنك معرفة كم عنصر بداخله (لا .size ولا .forEach).

لا يمكن نسخه أو عرضه:

console.log(ws); // WeakSet {}
JavaScript

🧠 متى تستخدم WeakSet؟

  • عندما تحتاج إلى تتبع كائنات مؤقتة بدون منع جمع القمامة (Garbage Collection).
  • في حالات تخزين مراجع بدون التأثير على دورة حياة الكائن
🧪 مثال عملي: تتبع الكائنات “المعالجة”
const processed = new WeakSet();

function process(user) {
  if (processed.has(user)) {
    console.log("User already processed");
    return;
  }

  // معالجة الكائن
  console.log("Processing user:", user.name);
  processed.add(user);
}

const user1 = { name: "Ahmed" };
process(user1); // Processing user: Ahmed
process(user1); // User already processed
JavaScript
خلاصة:
  • استخدم WeakSet عندما تريد تخزين كائنات فقط وتحتاج إلى أن تكون غير قابلة للتكرار أو العرض وتُزال تلقائيًا من الذاكرة عند عدم استخدامها.
  • لا تصلح للتعامل مع الأرقام أو النصوص أو القوائم التي تحتاج للتكرار أو الإحصاء.

✅ الفائدة:

  • يُستخدم في الحالات التي تحتاج إلى تتبع الكائنات دون التأثير على “جمع القمامة”.
  • مفيد في إدارة الذاكرة.
2. التعامل مع Set ضمن هيكل بيانات معقد

مثلاً: لديك Set داخل كائن أو داخل مصفوفة:

const users = [
  { name: "Ali", skills: new Set(["JS", "HTML"]) },
  { name: "Sara", skills: new Set(["CSS", "JS"]) }
];

// التحقق إن كانت مهارة موجودة
console.log(users[0].skills.has("HTML")); // true
JavaScript

4. تحديث قيمة داخل Set

لا يمكنك “تحديث” عنصر داخل Set مباشرة لأنه لا يحتوي على مفاتيح كـ Map.

ولكن يمكنك حذفه ثم إضافته من جديد:

const newSet = new Set([{ id: 1, name: "Ali" }, { id: 2, name: "Sara" }]);
let updated = { id: 1, name: "Yasin" };

const toDelete = [];

newSet.forEach(item => {
  if (item.id === 1) {
    toDelete.push(item);
  }
});

toDelete.forEach(item => {
  newSet.delete(item);
  newSet.add(updated);
});

console.log(newSet);
JavaScript
6. استخدام Set لحل مشاكل شائعة
🔹 إيجاد العناصر الفريدة من مصفوفة:
const arr = [1, 1, 2, 3, 4, 4];
const unique = [...new Set(arr)]; // [1, 2, 3, 4]
JavaScript

🔹 التحقق من وجود تكرار:

function hasDuplicate(arr) {
  return new Set(arr).size !== arr.length;
}
JavaScript
7. أداء Set مقابل Array في عمليات البحث
العمليةArraySet
.includes(value)أبطأ في المصفوفات الكبيرةhas(value) أسرع
الإضافةO(n) إذا استخدمت includes للتحققO(1)
الحذفO(n)O(1)
8. Set داخل JSON؟

⚠️ Set لا يُحول مباشرة إلى JSON:

const set = new Set([1, 2, 3]);
console.log(JSON.stringify(set)); // "{}" (فارغ!)
JavaScript

✅ الطريقة الصحيحة:

const json = JSON.stringify([...set]); // "[1,2,3]"
JavaScript

9. Set كفلتر بيانات ديناميكي

const filterTags = new Set();

function toggleTag(tag) {
  if (filterTags.has(tag)) {
    filterTags.delete(tag);
  } else {
    filterTags.add(tag);
  }
  console.log([...filterTags]);
}
JavaScript
🧠 هل هناك بديل لـ Set؟

نعم، إذا كنت تحتاج:

  • قيم فريدة + خصائص إضافية → استخدم Map أو Object بدلًا من Set.
  • قيم فريدة بدون تكرار فقط → Set هي الأفضل.
🧾 الخلاصة

إلى جانب شرحنا الأساسي، المواضيع التالية مرتبطة بـ Set:

الموضوعفائدة
WeakSetإدارة الكائنات بشكل أخف
تحويلات Set إلى Array و JSONلتسهيل المعالجة
مقارنة Setللتحقق من التساوي
تحديث العناصر داخل Setعبر الحذف والإضافة
الأداء مقابل المصفوفاتمهم للتطبيقات الكبيرة
استخدامها مع Map أو Objectفي هياكل بيانات مركبة