🧠 ما هو Set في JavaScript؟
Set هو نوع خاص من الكائنات Objects يُستخدم لتخزين قيم فريدة فقط (لا تتكرر) من أي نوع: بدائي أو كائن.
✅ خصائص Set الأساسية
| الخاصية | الوصف |
|---|---|
| لا يقبل القيم المكررة | يتم تجاهل أي قيمة مكررة مضافة. |
| يحافظ على الترتيب | القيم تحفظ بنفس ترتيب الإدخال. |
| يقبل أنواع بيانات مختلفة | يمكن إدخال أرقام، نصوص، كائنات، دوال، إلخ |
📦 إنشاء Set
✅ الصيغة:
const mySet = new Set();JavaScriptconst 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) | يضيف قيمة إلى الـ Set | mySet.add(5) |
delete(value) | يحذف قيمة من الـ Set | mySet.delete(5) |
has(value) | يتحقق هل القيمة موجودة | mySet.has(5) ➝ true/false |
clear() | يحذف كل العناصر | mySet.clear() |
size | عدد العناصر في الـ Set | mySet.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')); // falseJavaScript🔹 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); // 3JavaScript🔁 التكرار على 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
- التخلص من التكرار:
const nums = [1, 2, 2, 3, 4, 4];
const unique = [...new Set(nums)];
console.log(unique); // [1, 2, 3, 4]JavaScriptأداء أفضل في البحث (has) من المصفوفة الكبيرة.
تخزين البيانات المؤقتة أو القيم الفريدة مثل كلمات المرور المولدة أو معرفات الجلسة.
💡 مقارنات سريعة بين Set و Array
| الخاصية | Set | Array |
|---|---|---|
| القيم المكررة | لا يُسمح بها | يُسمح |
| الترتيب | يحافظ عليه | يحافظ عليه |
| البحث عن قيمة | 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); // 2JavaScript🔚 الخلاصة
| الميزة | التقييم |
|---|---|
| إزالة التكرار | ✅ ممتازة |
| أداء عند البحث | ✅ سريع |
| دعم أنواع متعددة | ✅ |
| سهولة التحويل إلى Array | ✅ |
1. WeakSet (مجموعة ضعيفة)
✅ ما هو؟
WeakSet هو نوع خاص من الكائنات في JavaScript يشبه Set، لكنه يأتي بقيود وخصائص مختلفة تجعله مفيدًا في حالات معينة، خصوصًا عند التعامل مع الكائنات (objects) فقط.
🔍 الفرق الأساسي بين Set و WeakSet
| الخاصية | Set | WeakSet |
|---|---|---|
| يدعم جميع أنواع القيم | ✅ نعم | ❌ لا، فقط الكائنات (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)); // falseJavaScriptconst 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)); // falseJavaScript⚠️ القيود:
لا يقبل القيم البدائية:
ws.add(1); // ❌ TypeErrorJavaScriptلا يمكنك معرفة كم عنصر بداخله (لا .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 processedJavaScriptخلاصة:
- استخدم
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")); // trueJavaScript4. تحديث قيمة داخل 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);JavaScript6. استخدام 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;
}JavaScript7. أداء Set مقابل Array في عمليات البحث
| العملية | Array | Set |
|---|---|---|
.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]"JavaScript9. 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 | في هياكل بيانات مركبة |