الفصول في جافا سكريبت

0 الأسهم
0
0
0
0

مقدمة

الفئات هي قوالب لإنشاء الكائنات. تُغلّف البيانات بالشفرة البرمجية للعمل عليها. تُبنى الفئات في جافا سكريبت على نماذج أولية، ولكنها تتميز أيضًا ببعض قواعد اللغة والدلالات الخاصة بها.

تعتبر الفئات في الأساس "وظائف خاصة"، وكما يمكنك تعريف تعبيرات الوظيفة وإعلانات الوظيفة، يمكن تعريف الفئة بطريقتين: تعبير الفئة أو إعلان الفئة.

// Declaration
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
// Expression; the class is anonymous but assigned to a variable
const Rectangle = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
// Expression; the class has its own name
const Rectangle = class Rectangle2 {
constructor(height, width) {
this.height = height;
this.width = width;
}
};

كما هو الحال مع إعلانات الدوال، قد تكون إعلانات الفئات مجهولة المصدر أو تحمل اسمًا مختلفًا عن المتغير المُخصص لها. ومع ذلك، بخلاف إعلانات الدوال، تخضع إعلانات الفئات لنفس القيود الزمنية للمنطقة الميتة مثل let أو const، وتتصرف كما لو أنها لم تُرفع.

جسم الفصل

جسم الفصل هو الجزء المحصور بين أقواس متعرجة {}. هذا هو المكان الذي تحدد فيه عناصر الفصل، مثل الأساليب أو المنشئين.

يتم تنفيذ جسم الفصل في الوضع الصارم، حتى بدون التوجيه "use strict".

يمكن وصف عنصر الفئة من خلال ثلاثة جوانب:

  • النوع: جهاز استقبال، منظم، طريقة أو مجال
  • الموقع: ثابت أو عينة
  • الرؤية: عامة أو خاصة

منشئ

طريقة البناء هي طريقة خاصة لإنشاء وتهيئة كائن مُنشأ باستخدام فئة. لا يمكن أن توجد سوى طريقة خاصة واحدة باسم "البناء" في الفئة - إذا احتوت الفئة على أكثر من مثيل واحد لطريقة البناء، فسيتم طرح خطأ بناء الجملة.

يمكن للمنشئ استخدام الكلمة الأساسية super لاستدعاء منشئ الفئة الفائقة.

يمكنك إنشاء خصائص مثيل داخل المنشئ:

class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}

بدلاً من ذلك، إذا كانت قيم خصائص المثيل الخاصة بك لا تعتمد على وسيطات المنشئ، فيمكنك تعريفها كحقول فئة.

كتل التهيئة الثابتة

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

من الممكن إعلان كتل ثابتة متعددة، ومن الممكن أن تتخلل هذه الكتل إعلانات الحقول والطرق الثابتة (يتم تقييم جميع العناصر الثابتة حسب ترتيب الإعلان).

طُرق

تُعرَّف الطرق على النموذج الأولي لكل مثيل من الفئة، وتتشاركها جميع المثيلات. يمكن أن تكون الطرق دوالًا بسيطة، أو دوالًا غير متزامنة، أو دوال مولدة، أو دوال مولدة غير متزامنة. لمزيد من المعلومات، راجع تعريفات الطرق.

class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea();
}
// Method
calcArea() {
return this.height * this.width;
}
*getSides() {
yield this.height;
yield this.width;
yield this.height;
yield this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area); // 100
console.log([...square.getSides()]); // [10, 10, 10, 10]

الأساليب والحقول الثابتة

تُعرّف الكلمة الأساسية static طريقةً أو حقلاً ثابتاً لفئة. تُعرّف الخصائص الثابتة (الحقول والطرق) على الفئة نفسها، وليس على كل مثيل. تُستخدم الطرق الثابتة غالباً لإنشاء دوال مساعدة لتطبيق ما، بينما تُفيد الحقول الثابتة في التخزين المؤقت، أو التكوين الثابت، أو أي بيانات أخرى لا تحتاج إلى التكرار عبر المثيلات.

class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static displayName = "Point";
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.hypot(dx, dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance; // undefined
p2.displayName; // undefined
p2.distance; // undefined
console.log(Point.displayName); // "Point"
console.log(Point.distance(p1, p2)); // 7.0710678118654755

الإعلانات الميدانية

باستخدام صيغة إعلان حقل الفصل، يمكن كتابة مثال المنشئ على النحو التالي:

class Rectangle {
height = 0;
width;
constructor(height, width) {
this.height = height;
this.width = width;
}
}

حقول الفئة تُشبه خصائص الكائن، وليست متغيرات، لذا لا نستخدم كلمات مفتاحية مثل const للإعلان عنها. في جافا سكريبت، تستخدم الخصائص الخاصة صيغة تعريف خاصة، لذا لا ينبغي استخدام كلمات مفتاحية معدلة مثل public وprivate أيضًا.

كما هو موضح أعلاه، يمكن تعريف الحقول بقيم افتراضية أو بدونها. الحقول التي لا تحتوي على قيم افتراضية لا تُعرّف افتراضيًا. بتعريف الحقول مُسبقًا، تُوثّق تعريفات الفئات بشكل أفضل، وتكون الحقول موجودة دائمًا، مما يُساعد على التحسين.

راجع حقول الفئة العامة للحصول على مزيد من المعلومات.

الممتلكات الخاصة

باستخدام الحقول الخاصة، يمكن تعديل التعريف على النحو التالي.

class Rectangle {
#height = 0;
#width;
constructor(height, width) {
this.#height = height;
this.#width = width;
}
}

من الخطأ الإشارة إلى الحقول الخاصة من خارج الفئة. لا يمكن قراءتها أو كتابتها إلا من داخل هيكل الفئة. بتحديد عناصر غير مرئية خارج الفئة، تضمن عدم اعتماد مستخدمي فئتك على العناصر الداخلية، والتي قد تتغير من إصدار لآخر.

لا يمكن الإعلان عن الحقول الخاصة إلا مسبقًا في إعلان حقل. ولا يمكن إنشاؤها لاحقًا بتعيينها، كما هو الحال مع الخصائص العادية.

انظر الملكية الخاصة لمزيد من المعلومات.

الميراث

تُستخدم الكلمة الأساسية extends في إعلانات الفئة أو تعبيرات الفئة لإنشاء فئة كطفل لمنشئ آخر (فئة أو دالة).

class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(`${this.name} barks.`);
}
}
const d = new Dog("Mitzie");
d.speak(); // Mitzie barks.

إذا كان هناك مُنشئ في الفئة الفرعية، فيجب عليه أولاً استدعاء super() قبل استخدامه. يمكن أيضًا استخدام الكلمة المفتاحية super لاستدعاء الدوال المرتبطة بالفئة العليا.

class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(`${this.name} roars.`);
}
}
const l = new Lion("Fuzzy");
l.speak();
// Fuzzy makes a noise.
// Fuzzy roars.

أمر التقييم

عند تقييم إعلان فئة أو تعبير فئة، يتم تقييم مكوناتها المختلفة بالترتيب التالي:

  1. يتم تقييم الجملة الموسعة، إن وجدت، أولاً. يجب تقييمها إلى دالة بناء صالحة أو قيمة فارغة، وإلا فسيتم طرح خطأ TypeError.
  2. يتم استخراج دالة المنشئ، وفي حال عدم وجودها، يُستبدل بالتنفيذ الافتراضي. مع ذلك، بما أن تعريف المنشئ هو مجرد تعريف دالة، فإن هذه الخطوة غير مرئية.
  3. يتم تقييم مفاتيح خصائص عناصر الفئة بالترتيب الذي أُعلنت به. في حال تقييم مفتاح الخاصية، يُعيَّن التعبير المُقيَّم بهذه القيمة إلى القيمة المحيطة بالفئة (وليس الفئة نفسها). لم يتم تقييم أيٍّ من قيم الخصائص بعد.
  4. يتم تثبيت الطرق والوصولات بالترتيب الذي تم إعلانها به. تُثبّت طرق الوصول والوصول الخاصة بالمثيل على خاصية النموذج الأولي للفئة الحالية، وتُثبّت الطرق والوصولات الثابتة على الفئة نفسها. يُحتفظ بطرق الوصول والوصول الخاصة بالمثيلات لتثبيتها مباشرةً على المثيل لاحقًا. هذه الخطوة غير مرئية.
  5. تم الآن تهيئة الفئة باستخدام النموذج الأولي المُحدد بواسطة الامتدادات والتنفيذ المُحدد بواسطة المُنشئ. في جميع الخطوات السابقة، إذا حاول تعبير مُقيّم الوصول إلى اسم الفئة، فسيتم طرح خطأ مرجعي لأن الفئة لم تُهيأ بعد.
  6. يتم تقييم قيم عناصر الفئة حسب ترتيب الإعلان:
  • لكل حقل مثيل (عام أو خاص)، يُخزَّن تعبير المُهيئ الخاص به. يُقيَّم المُهيئ عند إنشاء المثيل، أو في بداية المُنشئ (للفئات الأساسية)، أو مُباشرةً قبل عودة استدعاء super() (للفئات المُشتقة).
  • بالنسبة لكل حقل ثابت (عام أو خاص)، يتم تقييم تهيئته بهذه المجموعة إلى الفصل نفسه ويتم إنشاء الخاصية على الفصل.
  • يتم تقييم كتل التهيئة الثابتة بهذه المجموعة في الفصل نفسه.

أمثلة

ربط هذا بالطرق المثيلة والثابتة

عند استدعاء دالة ثابتة أو مثيلة بدون قيمة لها، على سبيل المثال، بتعيين الدالة إلى متغير ثم استدعائها، ستكون القيمة غير مُعرّفة داخل الدالة. يستمر هذا السلوك حتى في حالة عدم وجود تعليمة "استخدام صارم"، لأن الكود داخل نص الفئة يُنفّذ دائمًا في الوضع الصارم.

class Animal {
speak() {
return this;
}
static eat() {
return this;
}
}
const obj = new Animal();
obj.speak(); // the Animal object
const speak = obj.speak;
speak(); // undefined
Animal.eat(); // class Animal
const eat = Animal.eat;
eat(); // undefined

إذا أعدنا كتابة ما سبق باستخدام صيغة الدالة التقليدية في الحالة غير الصارمة، فسيتم تقييد استدعاءات هذه الدالة تلقائيًا بـ globalThis. في الحالة الصارمة، تبقى قيمة this غير مُعرّفة.

function Animal() {}
Animal.prototype.speak = function () {
return this;
};
Animal.eat = function () {
return this;
};
const obj = new Animal();
const speak = obj.speak;
speak(); // global object (in non–strict mode)
const eat = Animal.eat;
eat(); // global object (in non-strict mode)
اترك تعليقاً

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


قد يعجبك أيضاً