آشنایی با مفهوم Prototype ها

2
58
Prototype در جاوا اسکریپت

جاوا اسکریپت OOP: مفهوم Prototype در جاوا اسکریپت

در این جلسه به یکی از عجیب ترین و گیج کننده ترین قسمت های جاوا اسکریپت برای افراد مبتدی می رسیم: prototype ها! معمولا زبان های برنامه نویسی مشهور مانند Java و PHP و #C و امثالهم در زمینه ی شیء گرایی از کلاس ها استفاده می کنند. به عبارت دیگر شیء گرایی این زبان ها بر محوریت کلاس ها  تعریف شده است اما در نسخه ی ES5 زبان جاوا اسکریپت چنین چیزی را نداریم! اینجاست که اکثر افراد با مفهوم prototype آشنا می شوند که حسابی آن ها را گیج می کند.

به زبان ساده هر شیء در زبان جاوا اسکریپت یک prototype دارد و خود prototype نیز یک شیء است. تمام اشیاء جاوا اسکریپتی خصوصیات و متدهایشان را از prototype هایشان به ارث می برند. مثلا زمانی که در حال نوشتن Object literal هستید (یعنی به صورت دستی خودتان یک شیء را بنویسید) prototype شما object.prototype نام دارد. هنگامی که در حال ساخت یک شیء از طریق Constructor ها هستید (کلیدواژه ی new) مسئله متفاوت است. مثلا در جلسه ی قبل یک constructor به نام Person ساختیم بنابراین prototype ما Person.prototype است اما می توانید یک مرحله بالاتر بروید و به object.prototype دسترسی داشته باشید.

بگذارید در قالب یک مثال توضیح بدهم. از جلسه ی قبل constructor خودمان را کپی می کنیم:

من یک مورد (lastName) را نیز به این constructor اضافه کرده ام. حالا دو شیء جدید (نمونه یا instance) می سازم:

با اجرای کد بالا Mary را در کنسول مرورگر می بینیم. اگر به دقت نگاه کرده باشید یک خصوصیت به نام __Proto__ نیز قابل مشاهده است:

خصوصیت Proto
خصوصیت Proto

همانطور که می بینید این همان Person.prototype ما است. هر چیزی که درون Constructor خود بگذاریم در این قسمت دیده خواهد شد. اگر دقت کنید داخل همین __proto__ یک __proto__ دیگر داریم که همان Object.prototype ما است و prototype اصلی اشیاء در جاوا اسکریپت است:

proto دوم نشان دهنده ی prototype شیء اصلی در جاوا اسکریپت است
proto دوم نشان دهنده ی prototype شیء اصلی در جاوا اسکریپت است

می بینید که انواع متدها درون این prototype موجود است. Prototype در لغت به معنی «طرح اولیه» یا «پیش‌نمونه» یا «نخستین الگو» است بنابراین یک prototype در واقع یک طرح کلی و اولیه برای دسته ای از اشیاء است و می توان گفت به نوعی معادل کلاس ها می باشد.

 حالا به constructor خود (Person) برگردید. همانطور که می بینید هر شیء ای که از Person ساخته می شود باید نام، نام خانوادگی و تاریخ تولد را داشته باشد اما calculateAge برای همه ی این اشیاء یک تابع ثابت است و نیازی به تکرار آن نیست. بنابراین باید آن را داخل prototype بگذاریم نه خود شیء! برای اضافه کردن آن به prototype ابتدا آن را از داخل خود شیء کامنت کنید:

حالا به شکل زیر تابع calculateAge را به prototype خود اضافه می کنیم:

فایل خود را ذخیره کرده و به مرورگر بروید. مشاهده خواهید کرد که calculateAge به صورت یک متد به خود prototype متصل شده است:

متصل شدن calculateAge به prototype
متصل شدن calculateAge به prototype

برای استفاده از این متد نیز مانند قبل عمل می کنیم:

خروجی این کد عدد 27 خواهد بود بنابراین هیچ مشکلی در اجرای آن نداریم. برای تمرین بیشتر دو متد دیگر به نام های getFullName و getsMarried را نیز به آن اضافه می کنیم:

اگر با دستور Console.log از این متد استفاده کنیم برای getFullName مقدار Mary Johnson یا نام کامل این خانم را می گیریم. حالا فرض کنید این خانم ازدواج کند (در آمریکا رسم است که با ازدواج، زن فامیل مرد را به عنوان نام خانوادگی خودش انتخاب می کند) و بخواهد نام خانوادگی اش را تغییر دهد. متد getsMarried می تواند نام شیء ساخته شده را تغییر دهد! به مثال زیر توجه کنید:

در این کد ابتدا شیء mary را ساخته ایم و سپس با تابع getsMarried نام او را عوض کرده ایم. نتیجه در کنسول مرورگر به شکل زیر خواهد بود:

تغییر نام Mary پس از اجرای متد getsMarried
تغییر نام Mary پس از اجرای متد getsMarried

بنابراین متدها قدرت فراوانی برای تغییر داده ها و پویاسازی برنامه ی شما دارند و نهایتا این موضوع بر عهده ی شما است که از آن ها به صورت بهینه و دقیق استفاده کنید. قبل از پایان این بحث باید به نکته ی دیگری اشاره کنم: اگر یادتان باشد گفتم که ما می توانیم به prototype اصلی اشیاء در جاوا اسکریپت نیز دسترسی داشته باشیم:

proto دوم نشان دهنده ی prototype شیء اصلی در جاوا اسکریپت است
proto دوم نشان دهنده ی prototype شیء اصلی در جاوا اسکریپت است

این prototype برخی از متدهای آماده را برای ما دارد که برای مثال می خواهم از یکی از آن ها استفاده کنم (hasOwnProperty). متد hasOwnProperty به شیء شما نگاه می کند تا ببیند آیا این شیء خصوصیت (property) خاصی دارد یا خیر. ما می دانیم که اشیاء ما دارای خصوصیاتی مثل firstname و lastname و dob هستند بنابراین می توانیم آن را به شکل زیر امتحان کنیم:

نتیجه ی این دستور true خواهد بود چرا که ما چنین خصوصیتی را در شیء mary داریم.

حالا برای شما مثالی دارم. به نظر شما نتیجه ی کد زیر چیست؟

بله نتیجه False است چرا که ‘getFullName’ درون prototype است و بخشی از خود شیء mary نیست بنابراین به همین سادگی می توانیم بقیه ی موارد را نیز حساب کنیم.

امیدوارم با مفهوم prototype ها آشنا شده باشید. اگر دوست دارید با کلاس ها نیز آشنا شوید جای نگرانی نیست، در قسمت های بعدی به سراغ کلاس های معرفی شده در ES6 نیز خواهیم رفت اما فعلا باید مباحث ES5 را تکمیل کنیم.

ترتیبی که روکسو برای یادگیری مطالب سری شی گرایی در جاوا اسکریپت به شما توصیه می‌کند:

2 دیدگاه

  1. لطفا در مورد Arrow Function ها و This در Arrow Function ها هم یه مقاله ایجاد کنید تا بهتر بتونیم درکشون کنیم. تشکر

ارسال دیدگاه

لطفا دیدگاه خود را وارد کنید!
نام خود را وارد کنید