البرمجة الشيئية في 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. سننظر الآن في كيفية تحقيق ذلك.

المثال التالي هو استخدام عام لـ classJavaScript:

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