رايات الخصائص وواصفاتها في جافاسكربت
تعد جافاسكربت من أكثر اللغات البرمجية شهرةً واستخدامًا في عالم تطوير الويب. وهي لغة برمجة ديناميكية تُستخدم بشكل رئيسي في تطوير تطبيقات الويب التفاعلية، إذ توفر طريقة مرنة للتعامل مع عناصر صفحة الويب وعملياتها. من بين أهم المفاهيم التي تستخدمها جافاسكربت في التعامل مع البيانات هي الخصائص (Properties) والواصفات (Descriptors) الخاصة بالمتغيرات والكائنات. تعتبر هذه المفاهيم أساسية لفهم كيفية تعامل جافاسكربت مع البيانات والأشياء بشكل مرن وفعال.
1. الخصائص في جافاسكربت (Properties)
الخصائص في جافاسكربت هي سمات أو قيم مرتبطة بالكائنات أو المتغيرات. بعبارة أخرى، هي بيانات إضافية تخزن في الكائنات ويمكن الوصول إليها أو تعديلها. تُعتبر الخصائص أساسًا لبناء الكائنات في جافاسكربت، ويمكن أن تحتوي على أي نوع من البيانات: سواء كانت أرقامًا، أو نصوصًا، أو دوالًا، أو حتى كائنات أخرى.
1.1 إنشاء الخصائص
يمكن إنشاء الخصائص في جافاسكربت باستخدام مختلف الأساليب، مثل استخدام النقاط (dot notation) أو المصفوفات (bracket notation).
مثال باستخدام النقاط:
javascriptlet person = {};
person.name = "Ali";
person.age = 30;
في هذا المثال، قمنا بإنشاء كائن person وأضفنا له خاصيتين: name وage. يمكننا الوصول إلى هذه الخصائص باستخدام نفس الأسلوب:
javascriptconsole.log(person.name); // "Ali"
console.log(person.age); // 30
مثال باستخدام المصفوفات:
javascriptlet person = {};
person["name"] = "Ali";
person["age"] = 30;
هنا أيضًا أنشأنا الكائن person وأضفنا له الخصائص name وage، ولكننا استخدمنا المصفوفات بدلاً من النقاط.
1.2 تعديل الخصائص
يمكن تعديل الخصائص بسهولة في جافاسكربت ببساطة عن طريق تخصيص قيمة جديدة لها:
javascriptperson.name = "Ahmed"; // تغيير اسم الشخص
console.log(person.name); // "Ahmed"
1.3 حذف الخصائص
إذا كنت تريد حذف خاصية من الكائن، يمكنك استخدام الكلمة المفتاحية delete:
javascriptdelete person.age; // حذف خاصية العمر
console.log(person.age); // undefined
2. واصفات الخصائص (Property Descriptors)
تعتبر الواصفات في جافاسكربت جزءًا من مفهوم الخصائص المتقدمة، حيث تتيح للمطورين تعريف خصائص أكثر تعقيدًا وأبعادًا خاصة. الواصفات تحدد كيفية التفاعل مع الخصائص من خلال تحديد سلوكيات معينة مثل القابلية للتعديل، القابلية للإحصاء، والقابلية للإعادة.
2.1 أنواع الواصفات
واصفات الخصائص تكون عبارة عن كائنات تحتوي على عدة سمات محددة، مثل:
-
value: القيمة المرتبطة بالخاصية.
-
writable: يحدد ما إذا كانت الخاصية قابلة للتعديل.
-
enumerable: يحدد ما إذا كانت الخاصية قابلة للإحصاء (أي ما إذا كانت ستظهر في الحلقات مثل
for...inأو فيObject.keys()). -
configurable: يحدد ما إذا كانت الخاصية قابلة للتكوين (أي ما إذا كان من الممكن حذفها أو تعديل خصائصها).
2.2 استخدام Object.defineProperty()
لتحديد الواصفات الخاصة بالخصائص، يمكنك استخدام الدالة Object.defineProperty()، وهي دالة تتيح لك تحديد خاصية مع واصفات مخصصة لكائن ما.
مثال:
javascriptlet person = {};
Object.defineProperty(person, "name", {
value: "Ali",
writable: true,
enumerable: true,
configurable: true
});
console.log(person.name); // "Ali"
في هذا المثال، قمنا بتعريف خاصية name في الكائن person مع الواصفات الخاصة بها. قمنا بتحديد القيمة التي ستأخذها الخاصية، ما إذا كانت قابلة للتعديل (writable)، ما إذا كانت تظهر عند العد (enumerable)، وما إذا كانت يمكن حذفها أو تعديلها (configurable).
2.3 التعديل على الواصفات بعد التعريف
بمجرد أن يتم تعريف خاصية باستخدام Object.defineProperty()، يمكن تعديل الواصفات الخاصة بها (في حال كانت الواصفات قابلة للتعديل):
مثال لتغيير الواصفة writable:
javascriptObject.defineProperty(person, "name", {
writable: false
});
person.name = "Ahmed"; // لن يتغير الاسم لأن الخاصية غير قابلة للتعديل
console.log(person.name); // "Ali"
2.4 الواصفات غير القابلة للتعديل
إذا كانت الواصفات غير قابلة للتعديل (configurable: false)، فإنك لن تتمكن من تغييرها أو حذفها بعد أن تم تحديدها:
javascriptObject.defineProperty(person, "name", {
configurable: false
});
delete person.name; // لن يحدث أي شيء لأن الخاصية غير قابلة للحذف
console.log(person.name); // "Ali"
3. التلاعب بالخصائص باستخدام Object.getOwnPropertyDescriptor()
تعتبر دالة Object.getOwnPropertyDescriptor() وسيلة للوصول إلى الواصفات الخاصة بالخصائص. هذه الدالة تأخذ كائنًا واسم الخاصية، وتعيد كائنًا يحتوي على الواصفات الخاصة بتلك الخاصية.
مثال:
javascriptlet descriptor = Object.getOwnPropertyDescriptor(person, "name");
console.log(descriptor);
النتيجة ستكون كالتالي:
javascript{
value: "Ali",
writable: true,
enumerable: true,
configurable: true
}
4. الخصائص والإرث في جافاسكربت
في جافاسكربت، يمكن للخصائص أن تكون جزءًا من سلاسل وراثية، أي أن كائنًا قد يرث خصائص من كائن آخر. إذا كنت تستخدم الوراثة في جافاسكربت (من خلال البروتوتايب prototype)، فإن الخصائص التي لا توجد في الكائن الحالي يتم البحث عنها في سلسلة البروتوتايب.
مثال:
javascriptfunction Person(name, age) {
this.name = name;
this.age = age;
}
let ali = new Person("Ali", 30);
console.log(ali.name); // "Ali"
هنا، نلاحظ أن الكائن ali يحتوي على الخصائص name و age التي يتم إنشاؤها من خلال الدالة البنائية Person.
5. الخصائص المعرفة ديناميكيًا
يمكن أيضًا تعريف الخصائص ديناميكيًا في جافاسكربت، مما يعني أنه يمكن إضافة الخصائص أثناء تنفيذ البرنامج بناءً على الأحداث أو القيم المدخلة.
مثال:
javascriptlet person = {};
let propName = "email";
person[propName] = "[email protected]";
console.log(person.email); // "[email protected]"
6. التعامل مع الخصائص الداخلية لكائنات جافاسكربت
يمكننا استخدام الأدوات المتاحة في جافاسكربت للعمل مع الخصائص الخاصة بالكائنات، مثل Object.keys() للحصول على جميع المفاتيح، أو Object.getOwnPropertyNames() للحصول على جميع أسماء الخصائص حتى الخصائص غير القابلة للإحصاء.
javascriptlet person = {
name: "Ali",
age: 30
};
console.log(Object.keys(person)); // ["name", "age"]
console.log(Object.getOwnPropertyNames(person)); // ["name", "age"]
7. استخدام الـ WeakMap و WeakSet في التعامل مع الخصائص
في جافاسكربت، يُمكن استخدام WeakMap و WeakSet لتخزين خصائص متغيرة دون التأثير على دورة حياة الكائنات. هذه الهياكل تعتبر مثالية عندما تحتاج إلى تخزين بيانات ترتبط بكائنات معينة ولكن لا تريد أن تحتفظ تلك البيانات بقوة مرجعية للكائن، مما يؤدي إلى تسرب الذاكرة.
مثال على WeakMap:
javascriptlet weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "value");
console.log(weakMap.get(obj)); // "value"
8. خاتمة
إن التعامل مع الخصائص وواصفاتها في جافاسكربت يتطلب فهماً عميقًا لآليات الكائنات وديناميكياتها. يمكن للمطورين التحكم في طريقة تعامل جافاسكربت مع الخصائص عبر الواصفات لتخصيص سلوكيات معينة للخصائص، مما يزيد من مرونة الكود ويعزز كفاءته. كما أن استخدام أدوات مثل Object.defineProperty() و Object.getOwnPropertyDescriptor() يتيح القدرة على تكوين كائنات غنية بالخصائص التي تتسم

