البرمجة الشيئية في JavaScript - موضحة بأمثلة
JavaScript ليست لغة كائنية التوجه. ولكن لا يزال لديها طرق لاستخدام البرمجة الشيئية (OOP).
في هذا البرنامج التعليمي ، سأشرح OOP وأظهر لك كيفية استخدامه.
وفقًا لـ Wikipedia ، فإن البرمجة القائمة على الفصل هي
نمط من البرمجة الموجهة للكائنات (OOP) حيث تحدث الوراثة عن طريق تحديد فئات الكائنات ، بدلاً من حدوث الوراثة عبر الكائنات وحدها
النموذج الأكثر شيوعًا لـ OOP يعتمد على الفئة.
ولكن كما ذكرت ، فإن JavaScript ليس مقياس لغة قائم على التصنيف - إنه مقياس لغة قائم على النموذج الأولي.
وفقًا لتوثيق موزيلا:
اللغة القائمة على النموذج الأولي لها فكرة الكائن النموذجي ، وهو كائن يستخدم كقالب يمكن من خلاله الحصول على الخصائص الأولية لكائن جديد.
ألق نظرة على هذا الرمز:
let names = { fname: "Dillion", lname: "Megida" } console.log(names.fname); console.log(names.hasOwnProperty("mname")); // Expected Output // Dillion // false
متغير الكائن names
له خاصيتان فقط - fname
و lname
. لا توجد طرق على الإطلاق.
إذن من أين hasOwnProperty
تأتي؟
حسنًا ، إنه يأتي من Object
النموذج الأولي.
حاول تسجيل محتويات المتغير في وحدة التحكم:
console.log(names);
عند توسيع النتائج في وحدة التحكم ، ستحصل على هذا:

لاحظ الخاصية الأخيرة - __proto__
؟ حاول توسيعه:

سترى مجموعة من الخصائص تحت Object
المُنشئ. كل هذه الخصائص تأتي من Object
النموذج الأولي العالمي . إذا نظرت عن كثب ، ستلاحظ أيضًا مخبأنا hasOwnProperty
.
بمعنى آخر ، جميع الكائنات لديها حق الوصول إلى Object
النموذج الأولي. لا يمتلكون هذه الخصائص ، لكن يتم منحهم حق الوصول إلى الخصائص الموجودة في النموذج الأولي.
و __proto__
الملكية
يشير هذا إلى الكائن الذي يتم استخدامه كنموذج أولي.
هذه هي الخاصية الموجودة على كل كائن والتي تمنحه الوصول إلى Object prototype
الخاصية.
كل كائن لديه هذه الخاصية بشكل افتراضي ، والتي تشير إلى Object Protoype
ما عدا عندما يتم تكوينها بطريقة أخرى (أي عندما يشير الكائن __proto__
إلى نموذج أولي آخر).
تعديل __proto__
العقار
يمكن تعديل هذه الخاصية من خلال النص صراحة على أنها يجب أن تشير إلى نموذج أولي آخر. يتم استخدام الطرق التالية لتحقيق ذلك:
Object.create()
function DogObject(name, age) { let dog = Object.create(constructorObject); dog.name = name; dog.age = age; return dog; } let constructorObject = { speak: function(){ return "I am a dog" } } let bingo = DogObject("Bingo", 54); console.log(bingo);
في وحدة التحكم ، هذا ما لديك:

لاحظ __proto__
الخاصية speak
والطريقة؟
Object.create
يستخدم الوسيطة التي تم تمريرها إليه ليصبح النموذج الأولي.
new
كلمة رئيسية
function DogObject(name, age) { this.name = name; this.age = age; } DogObject.prototype.speak = function() { return "I am a dog"; } let john = new DogObject("John", 45);
john
الصورة __proto__
يتم توجيه خاصية DogObject
الصورة النموذج. لكن تذكر أن DogObject
النموذج الأولي هو كائن ( مفتاح وزوج قيم ) ، ومن ثم فإنه يحتوي أيضًا على __proto__
خاصية تشير إلى النموذج الأولي العام Object
.
يشار إلى هذه التقنية باسم تسلسل نموذجي .
علما بأن: على new
نهج الكلمة يفعل نفس الشيء Object.create()
ولكن فقط يجعل من السهل كما هو الحال بعض الأشياء تلقائيا بالنسبة لك.
و حينئذ...
كل كائن في Javascript له حق الوصول إلى Object
النموذج الأولي افتراضيًا. إذا تم تكوينه لاستخدام نموذج أولي آخر ، على سبيل المثال prototype2
، فسيكون prototype2
بإمكانه أيضًا الوصول إلى النموذج الأولي للكائن افتراضيًا ، وما إلى ذلك.
تركيبة الكائن + الوظيفة
ربما تكون في حيرة من أمرك من حقيقة DogObject
أنها دالة ( function DogObject(){}
) ولها خصائص يتم الوصول إليها من خلال تدوين النقطة . يشار إلى هذا باسم تركيبة كائن الوظيفة .
عندما يتم التصريح عن الوظائف ، يتم بشكل افتراضي منحها الكثير من الخصائص المرفقة بها. تذكر أن الوظائف هي أيضًا كائنات في أنواع بيانات JavaScript.
الآن ، كلاس
قدمت JavaScript class
الكلمة الرئيسية في ECMAScript 2015. مما يجعل JavaScript يبدو وكأنه لغة OOP. لكنه مجرد سكر تركيبي فوق تقنية النماذج الأولية الحالية. يواصل وضع النماذج الأولية في الخلفية ولكنه يجعل الجسم الخارجي يبدو مثل OOP. سننظر الآن في كيفية تحقيق ذلك.
المثال التالي هو استخدام عام لـ class
JavaScript:
class Animals { constructor(name, specie) { this.name = name; this.specie = specie; } sing() { return `${this.name} can sing`; } dance() { return `${this.name} can dance`; } } let bingo = new Animals("Bingo", "Hairy"); console.log(bingo);
هذه هي النتيجة في وحدة التحكم:

The __proto__
references the Animals
prototype (which in turn references the Object
prototype).
From this, we can see that the constructor defines the major features while everything outside the constructor (sing()
and dance()
) are the bonus features (prototypes).
In the background, using the new
keyword approach, the above translates to:
function Animals(name, specie) { this.name = name; this.specie = specie; } Animals.prototype.sing = function(){ return `${this.name} can sing`; } Animals.prototype.dance = function() { return `${this.name} can dance`; } let Bingo = new Animals("Bingo", "Hairy");
Subclassing
This is a feature in OOP where a class inherits features from a parent class but possesses extra features which the parent doesn't.
The idea here is, for example, say you want to create a cats class. Instead of creating the class from scratch - stating the name, age and species property afresh, you'd inherit those properties from the parent animals class.
This cats class can then have extra properties like color of whiskers.
Let's see how subclasses are done with class
.
Here, we need a parent which the subclass inherits from. Examine the following code:
class Animals { constructor(name, age) { this.name = name; this.age = age; } sing() { return `${this.name} can sing`; } dance() { return `${this.name} can dance`; } } class Cats extends Animals { constructor(name, age, whiskerColor) { super(name, age); this.whiskerColor = whiskerColor; } whiskers() { return `I have ${this.whiskerColor} whiskers`; } } let clara = new Cats("Clara", 33, "indigo");
With the above, we get the following outputs:
console.log(clara.sing()); console.log(clara.whiskers()); // Expected Output // "Clara can sing" // "I have indigo whiskers"
When you log the contents of clara out in the console, we have:

You'll notice that clara
has a __proto__
property which references the constructor Cats
and gets access to the whiskers()
method. This __proto__
property also has a __proto__
property which references the constructor Animals
thereby getting access to sing()
and dance()
. name
and age
are properties that exist on every object created from this.
Using the Object.create
method approach, the above translates to:
function Animals(name, age) { let newAnimal = Object.create(animalConstructor); newAnimal.name = name; newAnimal.age = age; return newAnimal; } let animalConstructor = { sing: function() { return `${this.name} can sing`; }, dance: function() { return `${this.name} can dance`; } } function Cats(name, age, whiskerColor) { let newCat = Animals(name, age); Object.setPrototypeOf(newCat, catConstructor); newCat.whiskerColor = whiskerColor; return newCat; } let catConstructor = { whiskers() { return `I have ${this.whiskerColor} whiskers`; } } Object.setPrototypeOf(catConstructor, animalConstructor); const clara = Cats("Clara", 33, "purple"); clara.sing(); clara.whiskers(); // Expected Output // "Clara can sing" // "I have purple whiskers"
Object.setPrototypeOf
is a method which takes in two arguments - the object (first argument) and the desired prototype (second argument).
From the above, the Animals
function returns an object with the animalConstructor
as prototype. The Cats
function returns an object with catConstructor
as it's prototype. catConstructor
on the other hand, is given a prototype of animalConstructor
.
لذلك ، يمكن للحيوانات العادية فقط الوصول إلى ، animalConstructor
ولكن القطط لها حق الوصول إلى catConstructor
و animalConstructor
.
تغليف
تستفيد JavaScript من طبيعة النموذج الأولي للترحيب بمطوري OOP في نظامها البيئي. كما يوفر طرقًا سهلة لإنشاء نماذج أولية وتنظيم البيانات ذات الصلة.
لا تقوم لغات OOP الحقيقية بإجراء نماذج أولية في الخلفية - فقط لاحظ ذلك.
شكر كبير لدورة Will Sentance حول Frontend Masters - JavaScript: الأجزاء الصلبة من JavaScript. لقد تعلمت كل ما تراه في هذه المقالة (بالإضافة إلى القليل من البحث الإضافي) من الدورة التدريبية. يجب عليك التحقق من ذلك.
يمكنك التواصل معي على Twitter على iamdillion لأية أسئلة أو مساهمات.
شكرا للقراءة : )
موارد مفيدة
- جافا سكريبت وجوه المنحى للمبتدئين
- مقدمة في البرمجة الشيئية في JavaScript