كائن `Map`

تشرح هذه المقالة كائن الـ Map۔

سوف نشرح خطوة بخطوة، من العمليات الأساسية إلى أمثلة عملية مفيدة في السيناريوهات الواقعية۔

YouTube Video

كائن Map

Map هو مجموعة تخزن أزواج المفتاح والقيمة۔ إنه مشابه للكائن، ولكنه يختلف في أن أي نوع، مثل الكائنات أو الدوال أو القيم البدائية، يمكن استخدامه كمفاتيح، كما يتم الحفاظ على ترتيب الإدخال.۔

أساسيات الـ Map

أولاً، دعنا نرى كيف ننشئ كائن Map وننفذ العمليات الأساسية۔

الكود التالي هو مثال بسيط يقوم بإنشاء خريطة فارغة، ويضيف مفاتيح، ويسترجع القيم.۔

1// Create an empty Map and add key-value pairs
2const m = new Map();
3m.set('a', 1);
4m.set('b', 2);
5
6console.log(m.get('a')); // 1
7console.log(m.size);     // 2
  • في هذا الكود، يمكنك إضافة العناصر باستخدام set، واسترجاع القيم باستخدام get، والتحقق من عدد العناصر باستخدام size۔
  • يحافظ كائن الـ Map على ترتيب الإدراج، مما يجعله مناسبًا للمعالجة المعتمدة على الترتيب۔

سلوك أوامر set، get، has، و delete

فيما يلي أمثلة على عمليات القراءة، الكتابة، التحقق من الوجود والحذف النموذجية۔

باستخدام الكود التالي، يمكنك التحقق من قيم الإرجاع وتأثير كل دالة۔

 1// Demonstrate set, get, has, and delete
 2const m2 = new Map();
 3m2.set('x', 10);
 4console.log(m2.has('x'));  // true
 5console.log(m2.get('y'));  // undefined
 6
 7m2.delete('x');
 8console.log(m2.has('x'));  // false
 9
10// set returns the map itself, allowing method chaining
11m2.set('a', 1).set('b', 2);
12console.log(m2);  // Map { 'a' => 1, 'b' => 2 }
  • تعيد get قيمة undefined إذا لم يكن المفتاح موجودًا۔ has يتحقق من وجود المفتاح، وdelete يزيل المفتاح.۔
  • أيضًا، لأن set تعيد الكائن Map نفسه، فإن ربط الدوال ممكن۔

يمكن استخدام أي نوع كمفتاح (بما في ذلك استخدام الكائنات كمفاتيح)

إحدى المزايا الرئيسية لـMap هي أنه يمكنك استخدام الكائنات مباشرة كمفاتيح.۔

يُظهر المثال التالي كيفية ربط القيم في كائن Map باستخدام الكائنات كمفاتيح۔

 1// Use objects as keys in a Map
 2const keyObj = { id: 1 };
 3const keyFunc = () => {};
 4const objMap = new Map();
 5
 6// Another object with the same content but a different reference
 7const anotherKeyObj = { id: 1 };
 8
 9objMap.set(keyObj, 'objectValue');
10objMap.set(keyFunc, 'functionValue');
11objMap.set(anotherKeyObj, 'anotherValue');
12
13console.log(objMap.get(keyObj));         // 'objectValue'
14console.log(objMap.get(keyFunc));        // 'functionValue'
15console.log(objMap.get(anotherKeyObj));  // 'anotherValue'
  • عند استخدام الكائنات كمفاتيح، من المهم أن تكون نفس المرجع۔ حتى لو كانت محتوياتها متشابهة، الكائنات ذات المراجع المختلفة تُعتبر مختلفة وليست نفس المفتاح۔

التكرار (الحلقات)

يحافظ الـ Map على ترتيب الإدراج، لذا غالبًا ما يُستخدم في التكرار۔

فيما يلي نوضح كيفية استخدام for...of، و forEach، ودوال keys()، values()، و entries()۔

 1// Iterating a Map with for...of and forEach
 2const iterMap = new Map([['a', 1], ['b', 2], ['c', 3]]);
 3
 4// for...of over entries (default)
 5for (const [key, value] of iterMap) {
 6  console.log(key, value);
 7}
 8
 9// forEach callback
10iterMap.forEach((value, key) => {
11  console.log(key, value);
12});
13
14// keys() and values()
15console.log([...iterMap.keys()]);   // ['a','b','c']
16console.log([...iterMap.values()]); // [1,2,3]
  • تعيد entries() مصفوفة من أزواج [key, value]، ويمكن تحويلها إلى مصفوفة باستخدام تركيب الانتشار۔ لاحظ أن الدالة المرتجعة لـ forEach تستقبل الوسيطات بالترتيب: value, key۔

التحويل بين Map و Object

يمكنك تحويل كائن موجود إلى Map، أو تحويل Map إلى كائن عادي أو مصفوفة۔

 1// Convert between Map and Object / Array
 2const obj = { a: 1, b: 2 };
 3const mapFromObj = new Map(Object.entries(obj)); // Object -> Map
 4console.log(mapFromObj.get('a')); // 1
 5
 6const objFromMap = Object.fromEntries(mapFromObj); // Map -> Object
 7console.log(objFromMap); // { a: 1, b: 2 }
 8
 9const arrayFromMap = [...mapFromObj]; // Map -> Array of [key, value]
10console.log(arrayFromMap); // [['a',1], ['b',2]]
  • استخدام Object.entries و Object.fromEntries يسهل عملية التحويل۔ ومع ذلك، نظرًا لأن مفاتيح الكائنات تقتصر على السلاسل أو الرموز، تضيع المفاتيح غير النصية عند التحويل مرة أخرى إلى كائن۔

نمط عملي: عد التكرار (Count Map)

عند حساب تكرار العناصر في مصفوفة، يجعل استخدام Map العملية أبسط.۔

الكود التالي هو مثال على استخدام كائن Map لعد تكرارات السلاسل النصية في مصفوفة وترتيبها۔

1// Count frequencies with Map
2const arr = ['apple','banana','apple','orange','banana','apple'];
3const freq = new Map();
4
5for (const item of arr) {
6  freq.set(item, (freq.get(item) || 0) + 1);
7}
8
9console.log([...freq.entries()]); // [['apple',3], ['banana',2], ['orange',1]]
  • يتيح استخدام الـ Map التحقق السهل من الوجود والتحديث۔ يمكن القيام بهذا باستخدام الكائنات أيضًا، لكن الـ Map قد يكون أكثر وضوحًا عند العمل مع مفاتيح عشوائية۔

ملاحظات حول Map و JSON.stringify (التسلسل)

لا يمكن لـ JSON.stringify تسلسل كائن Map مباشرة۔ إذا احتجت إلى حفظ كائن Map، يجب تحويله أولاً۔

يوضح المثال التالي كيفية تحويل Map إلى مصفوفة قبل تحويلها إلى JSON، وكيفية استرجاعها۔

1// Serialize and deserialize a Map
2const m3 = new Map([['x', 1], ['y', 2]]);
3const json = JSON.stringify([...m3]); // convert to array first
4console.log(json); // '[["x",1],["y",2]]'
5
6const restored = new Map(JSON.parse(json));
7console.log(restored.get('x')); // 1
  • يجب تحويل الكائنات Map التي تحتاج للحفظ أو النقل إلى مصفوفات قبل التسلسل۔ عند الاسترجاع، استخدم JSON.parse للتحويل إلى مصفوفة ثم أعد تحويلها إلى Map۔

مقدمة إلى WeakMap وكيفية استخدامه

يختلف WeakMap في أن مفاتيحه ذات مراجع ضعيفة (معرضة لجمع القمامة)۔

يعد مفيدًا لحفظ البيانات المؤقتة أو الفوقية باستخدام الكائنات كمفاتيح، ويتم تحريرها تلقائيًا عند جمع الكائن الرئيسي۔

1// WeakMap for metadata tied to object lifecycle
2const wm = new WeakMap();
3let obj = {};
4wm.set(obj, { meta: 'info' });
5console.log(wm.get(obj)); // { meta: 'info' }
6
7obj = null; // now the object can be GC'd and its entry removed from WeakMap
  • لا يمكن تعداد عناصر الـ WeakMap أو التحقق من حجمها، ولكنه مفيد لمنع تسرب الذاكرة۔

الملخص

Map هو مجموعة ملائمة، تسمح باستخدام أي نوع كمفتاح وتحتفظ بترتيب الإدراج على عكس الكائنات۔ من خلال فهم كل شيء من العمليات الأساسية إلى الاستخدامات المتقدمة، يمكنك إدارة البيانات بمرونة ووضوح أكبر۔ باستخدام Object و Map بشكل مناسب حسب حالة الاستخدام، يمكنك تحسين وضوح وقابلية قراءة الشيفرة بشكل كبير۔

يمكنك متابعة المقالة أعلاه باستخدام Visual Studio Code على قناتنا على YouTube.۔ يرجى التحقق من القناة على YouTube أيضًا.۔

YouTube Video