يمكننا توسيع الأصناف المضمّنة مثل المصفوفات والخرائط وغيرها. فمثلًا يرث صنف 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
:
كما ترى فليس هناك رابط بين التواريخ والكائنات، فهي مستقلة بذاتها. كائن Date.prototype
فقط هو من يرث Object.prototype
.
هذا فرق مهمّ للوراثة بين الكائنات المضمّنة في اللغة وتلك التي نحصل عليها باستعمال extends
.
ترجمة -وبتصرف- للفصل Extending built-in classes من كتاب The JavaScript language
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.