حقول الفئات وطرقها

الحقول

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

class MyClass {
    myField;
}

const myClassInstance = new MyClass();

myClassInstance;
> MyClass { myField: undefined }

يمكنك تهيئة حقل بقيمة. غالبًا ما تكون هذه قيمة افتراضية يمكن أن يستبدلها المنطق داخل الفصل:

class MyClass {
    myResult = false;
    set setValue( myValue ) {
        this.myResult = myValue;
    }
}
const myClassInstance = new MyClass();

myClassInstance;
> Object { myResult: false }

myClassInstance.setValue = true;

myClassInstance;\
> Object { myResult: true }

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

class MyClass {
    myField = true;
}

const myClassInstance = new MyClass();

myClassInstance.myField;
> true

myClassInstance.myField = false;

myClassInstance.myField;
> false;

توفّر الحقول أساسًا لبعض الميزات الأكثر تقدّمًا في الصفوف.

الحقول والطرق الخاصة

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

ولجعل الموقع خاصًا، أضِف # إلى بداية المعرّف عندما تفصح عنه:

class MyClass {
    #myPrivateField = true;
    #myPrivateMethod() {}
}
const myClassInstance = new MyClass();

myClassInstance;
> MyClass { #myPrivateField: true }
    #myPrivateField: true
    <prototype>: Object { … }
        constructor: class MyClass {}
        <prototype>: Object { … }

يجب الإعلان عن الحقل الخاص في نص الفئة التي تتضمن ذلك. يمكنك تغيير قيمته لاحقًا كسمة this، لكن لا يمكنك إنشاء الحقل باستخدام this.

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

class MyClass {
    #myResult = false;
    set setValue( myValue ) {
        this.#myResult = myValue;
    }
}
const myClassInstance = new MyClass();

myClassInstance;
> MyClass { #myResult: false }

myClassInstance.#myResult = true;
> Uncaught SyntaxError: reference to undeclared private field or method #myResult

myClassInstance.setValue = true;

myClassInstance;\
> MyClass { #myResult: true }

يُرجى العِلم أنّ وحدات تحكّم المطوّرين في المتصفحات تكون بشكل عام متساهلاً للغاية، ولكنها غير متسقة، في ما يتعلق بالسماح بالوصول إلى الحقول الخاصة لأغراض تصحيح الأخطاء:

class MyClass {
    #myPrivateField = true;
    #myPrivateMethod() {
        console.log( "This is inside a private method." );
    }
}
const myClassInstance = new MyClass();

myClassInstance;
> MyClass {#myPrivateField: true}

myClassInstance.#myPrivateField;
> true

myClassInstance.#myPrivateMethod();
> "This is inside a private method."
class MyClass {
    #myPrivateField = true;
    #myPrivateMethod() {
        console.log( "This is inside a private method." );
    }
}
const myClassInstance = new MyClass();

myClassInstance;
> MyClass {#myPrivateField: true}

myClassInstance.#myPrivateField;
> Uncaught SyntaxError: reference to undeclared private field or method #myPrivateField

myClassInstance.#myPrivateMethod();
> Uncaught SyntaxError: reference to undeclared private field or method #myPrivateMethod

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

class MyClass {
    #myPrivateField = true;
}
class ChildClass extends MyClass {
    childMethod() {
        console.log( this.#myPrivateField );
    }
}
> Uncaught SyntaxError: reference to undeclared private field or method #myPrivateField

الحقول والطرق الثابتة

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

لتحديد الحقول والطرق الثابتة في نص فئة، استخدِم الكلمة الرئيسية static:

class MyClass {
    static myStaticField;
    static myStaticMethod() {}
}
const myClassInstance = new MyClass();

يمكنك أيضًا استخدام الترميز النقطي لإنشاء طريقة ثابتة:

class MyClass {
    constructor() {}
}
MyClass.myStaticMethod = function() {}

لا يمكنك الوصول إلى الخصائص الثابتة من مثيل لفئتها، لكنها متوفرة في الدالة الإنشائية للفئة:

class MyClass {
    static myStaticField = true;
    static myStaticMethod() {
        console.log( "A static method." );
    }
}
const myClassInstance = new MyClass();

myClassInstance.myStaticField;
> undefined

myClassInstance.myStaticMethod();
> Uncaught TypeError: myClassInstance.myStaticMethod is not a function

MyClass.myStaticField;
> true

MyClass.myStaticMethod();
> "A static method."

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

class User {
    constructor( name, email ) {
        this.name = name;
        this.email = email;
    }
    static fromObject( myObject ) {
        return new User( myObject.name, myObject.email ?? "Omitted" );
    }
}
const userObject = {
    "name" : "My Name",
    "email" : "my@email.address"
};
const secondUserObject = {
    "name" : "My Name"
};

const firstUser = User.fromObject( userObject );
const secondUser = User.fromObject( secondUserObject );

firstUser;
> Object { name: "My Name", email: "my@email.address" }

secondUser;
> Object { name: "My Name", email: "Omitted" }

التحقق من فهمك

أي من أنواع الحقول التالية لا يمكن الوصول إليها إلا من داخل الفئة؟

الحقول الخاصة
حقول الفئات
Static fields