مشغل in في JavaScript: دليل شامل مع أمثلة عملية

دقائق القراءة: 5

عند تعلم JavaScript أو أي لغة برمجة أخرى، تعد المشغلات (Operators) من أولى المفاهيم التي ستصادفها. تشمل المشغلات الأكثر شيوعًا تلك الخاصة بالعمليات الحسابية، المنطقية، والمقارنة. ولكن هل كنت تعلم أن JavaScript تحتوي على مشغل in؟ إذا لم تكن كذلك، فلا تقلق. لقد صادفته مؤخرًا أثناء بحثي عن حل لمشكلة معينة.

في هذا المقال، ستتعلم بالضبط ما يفعله مشغل in في JavaScript، ومتى وكيف تستخدمه بفعالية.

ما هو مشغل in في JavaScript تحديداً؟

يُستخدم مشغل in في JavaScript للتحقق مما إذا كانت خاصية محددة موجودة في كائن (object) أو في خصائصه الموروثة (بمعنى آخر، في سلسلة النموذج الأولي prototype chain الخاصة به). يُعيد مشغل in القيمة true إذا كانت الخاصية المحددة موجودة، ويعيد false بخلاف ذلك.

تمثيل بصري لكائن JavaScript بسيط يوضح كيفية تعريف الخصائص والقيم داخله.

تُعد سلسلة النموذج الأولي (prototype chain) في JavaScript الآلية التي تُمكّن الكائنات أو نُسخ الكائنات (object instances) من الوصول إلى الخصائص والدوال التي لم تكن جزءًا أصليًا منها. ترث هذه الكائنات الخصائص والدوال المعرفة في مُنشئاتها (constructors) أو نماذجها الأولية (prototypes)، والتي يمكن الوصول إليها عبر خاصية __proto__ الخاصة بها.

يفترض هذا المقال أن لديك فهمًا أساسيًا لماهية الكائنات، وكيفية إنشائها، واستخداماتها، وكيف تعمل الوراثة (inheritance) في JavaScript. إذا لم يكن الأمر كذلك، فإن قراءة مقال حول أساسيات الكائنات في MDN قد يساعدك.

متى تستخدم مشغل in في JavaScript؟

1. للتحقق من وجود خاصية في كائن مباشر

يمكنك استخدام مشغل in ببساطة للتحقق مما إذا كانت خاصية معينة موجودة مباشرة ضمن كائن محدد.

const car = {
  make: 'Toyota',
  model: 'Camry',
  year: '2018',
  start: function() {
    console.log(`Starting ${this.make} ${this.model}, ${this.year}`);
  }
};

'make' in car; // تُعيد true لأن 'make' هي خاصية موجودة.
'start' in car; // تُعيد true لأن 'start' هي دالة (خاصية) موجودة.
'Toyota' in car; // تُعيد false. 'Toyota' ليست اسم خاصية، بل قيمة.

2. للتحقق من وجود خاصية موروثة في كائن

يُعد مشغل in مفيدًا أيضًا للتحقق من الخصائص التي يرثها الكائن من سلسلته النموذجية الأولية. لنستخدم بناء جملة الفئات (class syntax) في ES6 لإنشاء مُنشئ كائن. ينطبق هذا أيضًا على مُنشئات الدوال (function constructors):

class Car {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  start() {
    console.log(`Starting ${this.make} ${this.model}, ${this.year}`);
  }
}

const toyota = new Car('Toyota', 'Camry', '2018');

'start' in toyota; 
/* تُعيد true لأن 'toyota' هي نسخة من مُنشئ الكائن Car.
   وبالتالي، يرث الكائن 'toyota' جميع خصائص مُنشئ Car. */

'toString' in toyota; 
/* تُعيد true. 'toString' هي خاصية دالة من النوع Object،
   الذي يُعد مُنشئ Car نسخة منه. */

3. للتحقق من وجود فهرس/مفتاح في مصفوفة

قد تتساءل، بما أننا ذكرنا أن مشغل in في JavaScript يمكن استخدامه مع الكائنات، فلماذا يمكننا استخدامه أيضًا مع المصفوفات (arrays)؟ حسنًا، المصفوفة هي في الواقع نموذج أولي (instance) من النوع Object. في الواقع، كل شيء في JavaScript هو نسخة من النوع Object. قد يبدو هذا غريبًا، ولكن دعنا ننفذ برنامجًا بسيطًا في وحدة تحكم المتصفح (browser's console) للتأكيد.

أولاً، عرّف مصفوفة وتأكد مما إذا كانت نسخة من النوع Object باستخدام مشغل instanceof:

const number = [2, 3, 4, 5];
number instanceof Object; // تُعيد true

ما زلت في شك؟ اكتب number في وحدة التحكم واضغط Enter، ثم افتح المخرجات. ستلاحظ قائمة بالخصائص، إحداها هي __proto__ والتي تشير إلى Array. عند فتحها أيضًا والنزول في تلك القائمة، نصل إلى خاصية __proto__ أخرى بقيمة Object. هذا يوضح أن مصفوفة number هي نسخة من النوع Array، والذي هو بدوره نسخة من النوع Object.

الآن، نعود إلى استخدام مشغل in مع المصفوفات:

const number = [2, 3, 4, 5];

3 in number; // تُعيد true لأن 3 هو فهرس موجود في المصفوفة.
2 in number; // تُعيد true لأن 2 هو فهرس موجود في المصفوفة.
5 in number; // تُعيد false لأن 5 ليس فهرسًا موجودًا في المصفوفة، بل قيمة.

'filter' in number; 
/* تُعيد true لأن 'filter' هي خاصية دالة على النوع Array
   الذي تُعد مصفوفة 'number' نسخة منه. ترث مصفوفة 'number' خاصية 'filter'. */

4. للتحقق من وجود خاصية في عنصر HTML (DOM Element)

في مقال Kirupa بعنوان Check If You Are On a Touch Enabled Device، يسلط الضوء على هذه الدالة:

function isTouchSupported() {
  var msTouchEnabled = window.navigator.msMaxTouchPoints;
  var generalTouchEnabled = "ontouchstart" in document.createElement("div");

  if (msTouchEnabled || generalTouchEnabled) {
    return true;
  }
  return false;
}

تُعيد هذه الدالة true إذا كنت تستخدم جهازًا يدعم اللمس، وتُعيد false إذا كان الجهاز لا يدعم اللمس، وذلك عن طريق التحقق مما إذا كانت الخصائص window.navigator.msMaxTouchPoints و ontouchstart موجودة. هذه الخصائص لا توجد إلا في الأجهزة التي تدعم اللمس. الأمر بسيط ومباشر!

دعنا نركز على السطر المميز: "ontouchstart" in document.createElement("div"). تذكر كيف ذكرنا أن مشغل in يُعيد true إذا كانت الخاصية المحددة موجودة في كائن؟ عناصر HTML المستخدمة في JavaScript تصبح في الواقع نُسخًا من النوع Object، ومن هنا جاء اسم “نموذج كائن المستند” أو DOM.

بالطبع، قد لا تصدقني بدون نوع من الإثبات. كما فعلنا من قبل، دعنا نكتب بعض الأوامر في وحدة التحكم. أنشئ عنصر div واعرض خصائصه باستخدام console.dir():

const element = document.createElement('div');
console.dir(element);

سترى بعد ذلك عنصر div مع خصائصه المدرجة في وحدة التحكم. افتح القائمة المنسدلة وستلاحظ أن لديه خاصية __proto__ من النوع HtmlDivElement. افتحها وستجد خاصية __proto__ أخرى من النوع HtmlElement، ثم Element، Node، EventTarget، وأخيرًا Object. قم بتشغيل هذا أيضًا:

element instanceof Object;

سيُعيد هذا true، مما يوضح أن عنصر div هو نسخة من النوع Object، ولهذا السبب يمكن استخدام مشغل in عليه.

الخلاصة

لقد تعلمت عن مشغل in في JavaScript، والذي قد لا يكون شائعًا جدًا ولكنه قوي للغاية. يُستخدم هذا المشغل للتحقق من وجود الخصائص في كائن أو في نُسخ من النوع Object. يجب أن يكون هذا مفيدًا جدًا عند كتابة منطق التحقق من وجود الخصائص في تطبيقاتك.

الخلاصة التقنية

يُقدم مشغل in آلية قوية ومرنة للتحقق من وجود الخصائص، سواء كانت مباشرة أو موروثة عبر سلسلة النموذج الأولي، وهو ما يميزه عن طرق التحقق الأخرى مثل hasOwnProperty() التي تقتصر على الخصائص المباشرة. فهم كيفية عمل in مع الكائنات والمصفوفات وعناصر DOM يعزز من قدرة المطور على كتابة شيفرات أكثر قوة ودقة، خاصة في سيناريوهات الكشف عن الميزات (feature detection) أو التعامل مع بنى البيانات المعقدة. إنه أداة أساسية في صندوق أدوات أي مطور JavaScript يسعى لكتابة كود نظيف وموثوق.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *