في العديد من مؤتمرات المطور المشهور ****** كان يتحدث عن نمطه البديل لل prototypal pattern و هو ال OLOO

(سأتحدث عنه بعد قليل)

في مجمل حديثه عن طريقة عمل ال prototypal pattren أن الجافاسكربت ليس ليدها وراثة بل لديها behavior delegation أو "السلوك التوجهي" و كما يقول هو أن مفهوم كلمة الوراثة هو صنع نسخة من الشيء ، بمعنى آخر لنفرض أن الكائن A (الابن) ورثة من الكائن B(الأب) الدالة X هذا يعني أن الكائن A لديه نسخة من الدالة X التي في الكائن B و هذا ما لا تقوم به الجافاسكربت فهي تقوم على السلوك التوجهي وهو كالتالي :

لنفرض أن الكائن A (الابن) كائن فارغ وليس ليده أي Methods و أن لديه كائن أب وهو الكائن B و أن الكائن B لديه دالة X اذا حدث و قمت باستدعاء الدالة X من الكائن لابن A سوف لن يجد نسخة لدالة X في هذا الكائن بل من ثم سيتوجه ليرى ان كان لدى (الكائن الاب B) الدالة و من ثم يستدعيها و هذا هو الbehavior delegation .

و أيضا يقول أن الprottypal pattren مجرد محاولة مستمية لتقليد طريقة عمل الClasses أما ال OLOO هو الذي يتماشى مع ميكانيزم الغة فهو يعتمد على ال behavior delegation بشكل صريح عكس ال prototypal pattren فهو يعتمد على behavior delegation لكن بطريقة تشبه ال Classes .

سنتحدث أولاَ على ال prototypal pattren و كيفية استعماله لل behavior delegation أو *"السلوك التوجيهي" أولاََ.

سنوضح الأمر في المثال التالي :

حقيقة أن obj1 كان قادر على استدعاء الدالة talk ليس لأن obj1 لديه نسخة من الدالة talk و هذا ما يتبن في السطر 14 حيث استعملنا دالة hasOwnproperty ليرى ان كان هناك دالة اسمها talk.

فما قامت به الجافاسكربت لما استدعينا الدالة talk من obj1 بحثت في obj1 لم تجد الدالة من ثم

ذهبت الى A.prototype فوجدت الدالة هناك و استدعتها و هذا ما يسمى ب behavior delegation فهي ان لم تجد الدالة في الكائن توجهت الى ال prototype لتبحث هناك ان وجدت الدالة و استدعتها.

لآن سنتحدث عن ال OLOO Pattren :

هي اختصار لي جملة Objects Link to Other Objects وهي تعمل على ربط الكائنات ببعضها للحصول على نفس النتيجة في استعمالنا ل Prototypal Pattren بكود أنقى و أوضح و صريح في استعماله لسلوك التوجهي للجافاسكربت .

هذا نفس المثال السابق لكن بطريقة ال OLOO Pattren :

كما هو موضح في الكود لقد حولنا ال function Constructor A الى Object literal و وضعنا دالة init التي ستهيئ لنا الخواص في ال A Object و هذه ميزة رائعة في ال OLOO Pattren ففي ال Prototypal Pattren كنا مجبرين على تهيئة الخواص خلال انشائنا للدالة A.

ثم في السطر 25 اعتمدنا على ربط obj1 ب A ف الآن obj1 لا يحتوي على الدالة talk لكن في السطر 28 عند استدعائها بحثت الجافاسكربت على الدالة داخل obj1 و لم تجده و بما أننا ربطنا obj1 ب A بواسطة Object.create ستتوجه الجافاسكربت الى A لترى ان كان هناك دالة talk أو لا، فوجدتها و تم استدعائها و هنا قامت الجافاسكربت ب "السلوك التوجهي" فهي توجهت من obj1 الى A لتجد الدالة وهكذا . . .

هنا مثال آخر لكن بطريقة ال Prototypal Pattren و هو عبارة عن كود يقوم بئنشاء زر و يخبرنا أين تم الحاقه:

لاحظ في السطر 13 اضظررنا لستدعاء الدالة Widget يدوياً لتهيئ لنا الخصائص التي نحتاجها و أيضاً في السطر 21 استدعينا الدالة render من ال prototype الخاص ب Widget لأننا ان استدعينا الدالة بطريقة this.render ستحدث مشكلة اسمها Shadowing أي التظليل و ستقوم الدالة render التي في Button بتظليل على الدالة render التي في Widget لانهما يحملان نفس الاسم ف الجافاسكربت ستبحث عن render في button و ان وجدتها ستستدعيها و في هذه الحالة ستجدها و تحدث مشكلة التظليل و لأننا نريد render التي في Widget استخدمنا Widget.prototype.render.call لستدعائها من هناك بهته الطريقة الغريبة !

الآن نفس الكود لكن بطريقة ال OLOO Pattern :

كما في السابق لقد حولنا function Constructor Widget الى Object literal و وضعنا الدالة init لتهيئة الخصائص التي نريد و الدالة التي كانت في السابق render اسمها الآن insert تفادي لمشكلة التظليل

الآن لاحظ السطر 16 لم نعد بحاجة لستدعاء Widget بتلك الطريقة الغريبة فبدلا من ذالك تم استدعائها ب this.init لتهيئة الخصائص و في السطر 23 تم استدعاء الدالة insert بدلاً من الطريقة السابقة (Widget.prototype.render.call) أما في السطر 30 و 33 تم تهيئة الخصائص ل Button .

الآن و بعد كل الامثلة سنرى ميزات و عيوب OLOO Pattren

مميزات:

  • كود أنقى و مرتب و سهل لإحتفاظ.

  • سهل لتدريس و الفهم.

  • يتماشى مع ميكانيزم الجافاسكربت و كيفية عملها.

  • تخلصنا من new keyword و مشكلة نسيانها.

لا أعلم ان كان هذا عيب أم لا لكن ستبقى هناك مشكلة التظليل حيث لن نستطيع تسمية دالتين بنفس الاسم، لكن هكذا أفضل لأن تسمية دالتين بنفس الاسم فيه نوع التشويش و عدم فهم للكود البرمجي بينما اذا كان لكل دالة اسم خاص بها سيكون الامر منطقي.

على العموم ES6 قامت باضافة Classes و التي ماهي الى syntax sugar للمبرمجين الجدد في الغة لكي يظنو أن للجافاسكربت Classes و ما الى ذالك، بينما ما هي الى prototypal Pattren أو behavior delegation ان صح القول.

ما رأيك أنت بطريقة OLOO و استبدالها ب طريقة Prototypal pattren خصوصاَ و أن لهما نفس سرعة الآداء شخصياً أحبذ هذه الطريقة لأنها سهلة في التعامل .

مصادر :