FullStackJavaScript

فئات(classes) JavaScripts – تحت غطاء المحرك

كتب بواسطة: 15/12/2019 لا يوجد تعليقات

إن فئات (classes) JavaScript ليست سوى مجرد تكتيك أساسه نماذج أولية قائمة على التوريث ودوال البناء. ولكي نفهم الفكرة من فئات JS (JS classes)، نحتاج إلى فهم دوال البناء والنماذج الأولية والمفاهيم الأخرى ذات الصلة.

  1. دوال البناء (Constructor)

بما أن Javascript هي لغة برمجة وظيفية (functional) حيث كل شيء هو مجرد دالة، من أجل أن يكون هناك فئة (class) مثل (إنشاء مخطط تفصيلي للكائنات التي سيتم إنشائها)  وظيفياً في JavaScript، فإنه يتم استخدام دوال البناء (Constructor) لعمل ذلك، لترى كيفية عمل دوال البناء:

فئات JavaScript classes article- Constructor

توفر الدالة المذكورة أعلاه وظائف مماثلة تقريبا لوظيفة الـ class في الـ Java، ولإنشاء كائن (object) من نوع Vehicle نقوم بما يلي:

فئات JavaScript classes article- object

هذا رائع. أليس كذلك؟ الآن، يمكننا إنشاء العديد من الكائنات (objects) من نوع Vehicle كما نريد فقط بكتابة كود سطر واحد.

ولكن انتظر، هناك بعض المشاكل في هذه التقنية.

عندما نكتب new Vehicle()، ما يفعله محرك JavaScript تحت غطاء المحرك هو أنه يصنع نسخة من Vehicle  دالة بناء (constructor) الكائنات (objects) الخاصة بنا، كل خاصية وكل دالة يتم نسخها إلى النموذج (instance) الجديد لـ Vehicle، حسنا، ما المشكلة في هذا؟!

المشكلة هنا هي أننا لا نريد تكرار دوال الأعضاء (method) لدالة البناء (constructor) في كل كائن (object). وهو أمر زائد عن الحاجة. أليس كذلك؟ مشكلة أخرى هي أنه لا يمكننا إضافة خاصية أو دالة جديدة إلى كائن (object) موجود مثل هذا:

فئات JavaScript classes article- Constructor 2

لإضافة هذه السنة (year) ستحتاج لإضافتها لدالة البناء (constructor) نفسها:

فئات JavaScript classes article- Constructor year
  1. النموذج الأولي

عندما يتم إنشاء دالة جديدة في JavaScript يضيف محرك JavaScript بشكل افتراضي خاصية النموذج الأولي (prototype)  لها، فإن هذه الخاصية هي object ونسميه “كائن النموذج الأولي” (prototype object). بشكل افتراضي، يحتوي هذا النموذج الأولي على خاصية البناء (constructor ) والتي تشير إلى الدالة، والخاصية الأخرى __proto_ و التي هي كائن (object)، انظر إلى التالي:

فئات JavaScript classes article- Constructor 3

تسمى الخاصية __proto_ رواسب النموذج الأولي (dunder proto) وهي تشير إلى خاصية النموذج الأولي (prototype)  لدالة البناء (constructor) الخاصة بنا.

“الكلمة dunder جاءت من بايثون، حيث تسمى الأسماء المتغيرة التي تكون بين قوسين مع شرطات سفلية مزدوجة (double underscores) باسم dunder”.

كلما تم إنشاء نموذج (instance) جديد لدالة  البناء (constructor) يتم نسخ هذه الخاصية أيضا إلى النموذج (instance) مع خصائص ودوال أخرى:

فئات JavaScript classes article- Constructor 4

الآن، يمكن إستخدام كائن (object) النموذج الأولي  هذا لإضافة خصائص و دوال جديدة إلى دالة البناء (constructor) باستخدام تنسيق الجملة التالي وستكون متاحة لكل نماذج (instances) دالة البناء (constructor):

فئات JavaScript classes article- Constructor year 2

النموذج الأولي (prototype) رائع، ولكن هناك بعض الأشياء التي تحتاج إلى الحذر أثناء استخدام طريقة  النموذج الأولي (prototype). يتم تقاسم خصائص النموذج الأولي والدوال بين جميع نماذج (instances) دالة البناء (constructor)  ولكن عندما يحدث أي تغيير في أي خاصية بدائية من خصائص نموذج(instance) دالة البناء (constructor)، فإنه سينعكس فقط في ذلك النموذج (instance) وليس في جميع النماذج (instances):

فئات JavaScript classes article- 
instances Constructor

شيء آخر هو أن خصائص  النوع ذا المرجع (reference type) يتم مشاركتها دائما بين كل النماذج (instances)، على سبيل المثال، خاصية نوع المصفوفة، إذا تم تعديلها بواسطة  نموذج (instance) واحد من دالة البناء (constructor) سيتم تعديلها لكل النماذج (instances):

فئات JavaScript classes article- 
instances Constructor 2

هناك مقال ممتع جداً  أكثر تفصيلاً عن النموذج الأولي (prototype) هنا.

  1. الفئات (classes)

فهمنا  دوال البناء (constructor functions) والنموذج الأولي (prototype)، الآن أصبح من السهل فهم الفئة (class)، لماذا؟ لأن فئات JavaScript ليست سوى طريقة جديدة لكتابة دوال البناء (constructor) باستخدام قوة النموذج الأولي (prototype)، دعونا نرى مثالاً لهذا:

فئات JavaScript classes article- 
1

ومن أجل إنشاء نموذج (instance) جديد من فئة (class) Vehicle نقوم بهذا:

فئات JavaScript classes article- 
 vehicle

لذا إذا قارنت هذا مع ما قمنا به في البداية أثناء شرح دوال البناء (constructor)، فإنه مشابه جدًا له.

بكتابة الكود المذكور أعلاه، قمنا بالفعل بإنشاء متغير يسمى Vehicle  يشير إلى دالة البناء (constructor) المعرّفة في الفئة (class)، كما أضفنا دالة (method) إلى النموذج الأولي (prototype) للمتغير vehicle كما هو موضح بالأسفل:

فئات JavaScript classes article- 
3

إذا، هذا يثبت أن الفئة (class) هي طريقة جديدة لعمل دوال البناء (constructor). نعم، لكن هناك القليل من الأشياء الجديدة التي تم تقديمها وبعض القواعد التي تم وضعها من أجل جعلها أكثر تشابهاً بالفئات (classes) الفعلية.

  1. يتطلب البناء (constructor) الكلمة المفتاحية new لتعمل. هذا يعني أنه سيتم استدعاء البناء (constructor) فقط عندما نقوم بما يلي:
فئات JavaScript classes article-5

لكن في دالة البناء (constructor function) نستطيع فعلياً عمل هذا: 

فئات JavaScript classes article 7

يحدث هذا إذا حاولت إنشاء متغير فئة (class)  كما تم أعلاه:

فئات JavaScript classes article
8

2. دوال الفئة (class) غير قابلة للتعداد (non-enumerable). في Javascript، كل خاصية في الكائن (object) لها عَلم قابل للتعداد (enumerable)، وهذا العلم يحدد مدى توافره لبعض العمليات التي سيتم تنفيذها على تلك الخاصية. يحدد الفصل هذا العلم على أنه خاطئ (false) لكل الدوال المعرفة في نموذجه الأولي (prototype).

3. إذا لم تقم بإضافة البناء (constructor) إلى فئة (class)، ستتم إضافة بناء (constructor) فارغ افتراضي تلقائياً. مثل:

4. الكود داخل الفئة (class) يكون دائماً في وضع دقيق (strict)، هذا يساعد على كتابة كود خالي من الأخطاء، عن طريق إلقاء الأخطاء، بسوء في الكتابة أو أخطاء في الجملة أثناء كتابة الكود، أو حتى إزالة بعض الأكواد عن طريق الخطأ، والتي تكون مُستدعاة من مكان آخر.

5. تعريف الفئة (class) لا يرفع (hoisted). الرفع في JavaScript هو سلوك يتم فيه نقل كل التعريفات (declarations) تلقائياً فوق النطاق (scope) الحالي، هذا السلوك يتيح لك استخدام متغير أو دالة قبل أن يتم تعريفها.

لذا فإن تعريفات الفئة (class) ليست مرفوعة (hoisted)، ولا يمكنك استخدام فئة قبل تعريفها، وسوف يُرجع خطأ غير معرف (not defined) انظر أدناه:

وهذا ينجح:

فئات JavaScript classes article
10

لكن هذا لا:

فئات JavaScript classes article
11

6. لا تسمح الفئات تعيين قيمة للخاصية، مثل دوال الإنشاء (constructor functions) أو  حرفية الكائن (literal object). يمكنك فقط الحصول على دوال أو جلب (getter)/ تعيين (setter). إذاً لا يوجد تعريف لـ خاصية: القيمة  (property:value) مباشرة في الفئة (class).

4. ميزات الفئة (class)

1. البناء (constructor)

البناء (constructor) هو دالة خاصة في تعريف الفئة (class)، والذي يعرف الدالة، التي تمثل الفئة (class) نفسها. عندما تقوم بإنشاء نموذج (instance) فئة (class)، يتم إستدعاء البناء (constructor) تلقائياً.

فئات JavaScript classes article
constructor new vehicle

يمكن أن يستخدم البناء (constructor) الكلمة المفتاحية super لاستدعاء  بناء (constructor) الفئة (class) التي تكون تابعة لها.

لا يمكن أن تحتوي الفئة (class) على أكثر من دالة بناء واحدة.

2. دوال ثابتة (Static)

الدوال الثابتة هي دوال على الفئة (class) نفسها، وليس على النموذج الأولي (prototype) لها، على عكس الدوال الأخرى في الفئة (class)، والتي يتم تعريفها على النموذج الأولي (prototype).

الدوال الثابتة يتم تعريفها  باستخدام الكلمة الأساسية الثابتة (static)، ويتم إستخدامها غالباً  لإنشاء دوال الوظائف. يتم استدعاؤها دون إنشاء نموذج (instance) الفئة. انظر المثال أدناه.

تذكر، لا يمكن استدعاء الدوال الثابتة من نموذج (instance) الفئة (class).

3. الجلب (Getters) / التعيين (Setters)

يمكن أن يكون للفئة أيضاً  getter/setters للحصول على قيمة الخاصية أو لتعيين قيم الخاصية. شيء يشبه ما يلي.

تحت المحرك، يتم تعريف الـ getters/setters في فئة النموذج الأولي (prototype).

4. الفئة الفرعية (subclassing)

الفئة الفرعية هي  طريقة يمكنك بها تطبيق التوريث في فئات JavaScripts، يتم استخدام الكلمة المفتاحية extends  لإنشاء فئة فرعية من الفئة (class).

لنأخذ مثالاً:

يمكنك أن ترى عند إستدعاء دالة getName ()، دالة من الفئة الابن (child) تم استدعاؤها.

أحياناً نحتاج إلى استدعاء دالة الفئة (class) الأساسية. نستخدم الكلمة المفتاحية super من أجل استدعاء دوال الفئة الأساسية من خلال دالة الفئة الابن (child).

تغيير دالة getName () في الفئة الابن (child) إلى شيء مثل هذا:

الآن، إذا  استدعيت getName() من النموذج (instance) يجب أن ترجع النتيجة كما يلي:

إذاً حاولنا شرح الفكرة وراء فئات Javascript وفي النهاية تعلمنا بعض ميزات الفئات.

من المؤكد أنني لم أتطرق إلى الكثير من التفاصيل حول الموضوع، يمكنك متابعة القراءة من خلال متابعة مقالات رائعة كتبها المهوسون بـ Javascript ، ليس هذا فقط، هناك أطنان من المقالات الأخرى المتوفرة على الإنترنت، التي يمكن أن تساعدك على فهم الفكرة وراء فئات الJavascript.

المراجع:

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
  2. http://2ality.com/2015/02/es6-classes-final.html
  3. https://javascript.info/class
  4. https://thejsguy.com/tutorials/javascript-constructor-functions-and-classes
  5. https://www.phpied.com/3-ways-to-define-a-javascript-class/

اترك تعليق