🧠 ما هو 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')); // 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
- التخلص من التكرار:
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); // 2
JavaScript🔚 الخلاصة
الميزة | التقييم |
---|---|
إزالة التكرار | ✅ ممتازة |
أداء عند البحث | ✅ سريع |
دعم أنواع متعددة | ✅ |
سهولة التحويل إلى 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)); // false
JavaScriptconst 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
JavaScript4. تحديث قيمة داخل 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 | في هياكل بيانات مركبة |