دليل تعلم جافاسكربت توسعة الأصناف المضمنة في جافاسكربت


صفا الفليج

يمكننا توسيع الأصناف المضمّنة مثل المصفوفات والخرائط وغيرها. فمثلًا يرث صنف PowerArray من المصفوفة Array الأصيلة:

// نُضيف تابِعًا آخر إليها (أو أكثر لو أردنا‫)
class PowerArray extends Array {
  isEmpty() {
    return this.length === 0;
  }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

let filteredArr = arr.filter(item => item >= 10);
alert(filteredArr); // 10, 50
alert(filteredArr.isEmpty()); // false

من الجدير بالملاحظة أن التوابع المضمّنة في اللغة مثل: filter و map وغيرهم، تعيد كائنات جديدة من نفس النوع الموروث بالضبط PowerArray. وذلك لأن التطبيق الداخلي للتوابع يستخدم الباني المخصص لتلك الكائنات. في المثال أعلاه:

arr.constructor === PowerArray

متى استدعينا arr.filter()‎ أنشأ التابِع داخليًا مصفوفةً جديدة من النتائج باستعمال arr.constructor ذاتها، وليس المصفوفة العادية Array. هذا أمر رائع جدًا إذ يمكننا استعمال توابِع PowerArray على النتائج أيضًا.

يمكننا حتّى تخصيص هذا السلوك كما نرغب. فنُضيف جالِبًا ثابتًا Symbol.species إلى الصنف. لو كان موجودًا فسيُعيد الباني الذي ستستعمله جافاسكربت داخليًا لإنشاء المدخلات الجديدة في التوابِع map و filter وغيرها.

لو أردنا من التوابِع المضمّنة مثل map و filter - لو أردنا أن تُعيد المصفوفات الطبيعية، فعلينا إعادة صنف Array في رمز Symbol.species هكذا:

class PowerArray extends Array {
  isEmpty() {
    return this.length === 0;
  }

  // ستستعمل التوابِع المضمّنة هذا الصنف ليكون بانيًا
  static get [Symbol.species]() {
    return Array;
  }
}

let arr = new PowerArray(1, 2, 5, 10, 50);
alert(arr.isEmpty()); // false

// يصنع التابِع ‫ filter مصفوفةً جديدة باستعمال arr.constructor[Symbol.species]‎ بانيًا
let filteredArr = arr.filter(item => item >= 10);

// نوع ‫ filteredArr ليس PowerArray بل Array
alert(filteredArr.isEmpty()); // Error: filteredArr.isEmpty is not a function

كما نرى فالآن يُعيد التابِع ‎.filter مصفوفةً Array. بذلك تلك الميزة الموسّعة لن تُمرّر أكثر وأكثر.

ملاحظة: هنالك مجموعات أخرى تعمل بنفس الطريقة مثل: Map أو Set ويستخدمون أيضًا Symbol.species.

الأنواع المضمّنة لا ترث الثوابت

للكائنات المضمّنة أيضًا توابِع ثابتة مثل Object.keys و Array.isArray وغيرها.

وكما نعلم فالأصناف الأصيلة تُوسّع نفسها. فمثلًا تُوسّع المصفوفات Array الكائناتَ Object.

وعادةً متى وسّع الصنف صنفًا آخر ورث التوابِع الثابتة وغير الثابتة. شرحنا هذا بالتفصيل في المقال ”الخاصيات والتوابع الثابتة“.

ولكن الأصناف المضمّنة في اللغة استثناء لهذا، ولا ترث الحقول الثابتة من بعضها البعض.

مثال: ترث المصفوفات والتواريخ الكائناتَ، بذلك نرى لسيروراتها توابِع أتت من Object.prototype. ولكنّ كائن Array.[[Prototype]]‎ لا يُشير إلى Array، بذلك لا نرى توابِع ثابتة مثل Array.keys()‎ أوArray.keys()‎ مثلًا.

تغني الصورة عن ألف كلمة، إليك واحدة توضّح بنية التواريخ Date والكائنات Object:

object-date-inheritance.png

كما ترى فليس هناك رابط بين التواريخ والكائنات، فهي مستقلة بذاتها. كائن Date.prototype فقط هو من يرث Object.prototype.

هذا فرق مهمّ للوراثة بين الكائنات المضمّنة في اللغة وتلك التي نحصل عليها باستعمال extends.

ترجمة -وبتصرف- للفصل Extending built-in classes من كتاب The JavaScript language





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن