اساس جاوااسکریپت رو آبجکتها و پروتوتایپها تشکیل میدن و درک پروتوتایپها کمک بزرگی به درک نحوه کارایی جاوااسکریپت میکنه( منبع متن سایت https://ditty.ir/courses/javascript/prototypes/nYLA5)
سلام دوستان. پروتوتایپ (Prototype) یکی از مهمترین مفهومها توی جاوااسکریت هست و اگه اون رو خوب و کامل درک کنیم، یک قدم بزرگ توی فهم این زبان جذاب برداشتیم. حتماً شنیدیم که جاوااسکریپت ویژگیها و رفتارهایی داره که اگه اون رو با بقیه زبانها مقایسه کنیم عجیب به نظر میان. اما نباید انتظار داشته باشیم هر زبانی دقیقاً رفتاری رو ارائه بده که توی زبانهای دیگه وجود داره. اگه اینطور بود، دلیلی برای معرفی شدن زبانهای مختلف وجود نداشت. همونطور که مقایسه زبانهای محاورهای کار بیمعنی هست و هر زبانی گرامر و ساختار خودش رو داره و ما هیچ وقت نمیتونیم با ذهنیت قبلی از یک زبان، یک زبان دیگه رو یاد بگیریم.
توی این قسمت میخوایم با مفهوم پروتوتایپ توی جاوااسکریپت آشنا بشیم.
توی این قسمت یاد میگیریم که:
1- پروتوتایپ یعنی چی
2 - زنجیرهی پروتوتایپ چیه
معنی لغوی پروتوتایپ یعنی نمونهی اولیه. درک همین جمله خیلی میتونه کمککننده باشه. هر مقداری که توی جاوااسکریپت تعریف میکنیم، یک سری از ویژگیهاش رو از یک نمونهی اولیه به ارث میبره. این ویژگیها شامل متدها و پراپرتیهای مفید هستن که ما فکر میکنیم توی مقداری که ساختیم وجود دارن. در صورتی که موقع ساخته شدن، از یک والد به ارث برده میشن. مثل پراپرتی length
توی رشتهها و آرایهها. این موضوع رو با مثال بهتر میشه توضیح داد. کد زیر رو در نظر بگیرین:
const person = {
name: "Mario"
}
alert(person.toString()); // [object Object]
توی خط آخر ما از یک متد به اسم toString
طوری استفاده کردیم که انگار توی آبجکت person
از قبل تعریف شده. اما ظاهراً چنین متدی توی این آبجکت دیده نمیشه. پس این متد چطور در دسترس هست؟ 🤔 جواب پروتوتایپ یا نمونه اولیه هست.
وقتی مثل خط اول یک آبجکت داره ساخته میشه، یک سری از ویژگیها از آبجکت والد به ارث برده میشه. آبجکت والد برای person
، یک آبجکت درونی جاوااسکریپت به اسم Object
هست.
همونطور که گفته شد، توی جاوااسکریپت هر آبجکتی دارای یک پراپرتی مخفی به اسم [[Prototype]]
هست که به عنوان یک لینک به آبجکت بالاتر (والد) عمل میکنه. اون آبجکت هم خودش ممکنه شامل یک پراپرتی prototype
باشه که به یک آبجکت بالاتر اشاره میکنه. به این زنجیره، زنجیرهی پروتوتایپ گفته میشه.
میخوایم کدی بنویسیم که آبجکت person
به عنوان پروتوتایپ (والد) برای یک آبجکت دیگه در نظر گرفته بشه:
const parent = { name: "Mario" } const child = Object.create(parent);
با متد Object.create میتونیم یک آبجکت با یک پروتوتایپ دلخواه درست کنیم. پروتوتایپ مد نظرمون رو باید به عنوان آرگومان اول به این متد پاس بدیم. وقتی یک عضو (پراپرتی یا متد) رو از یک آبجکت رو صدا میزنیم، جاوااسکریپت دنبال این عضو توی همون آبجکت میگرده. اگه نتونست پیدا کنه، توی پروتوتایپ دنبالش میگرده. و باز هم اگه نتونست پیدا کنه، جستجو توی زنجیرهٔ پروتوتایپ ادامه داره تا جایی که هیچ پروتوتایپی وجود نداشته باشه:
const parent = { name: "Mario" } const child = Object.create(parent); console.log(child); // {} alert(child.name); // Mario
همونطور که میبینیم، به name
دسترسی داریم با اینکه این پراپرتی توی child
وجود نداره.
توی کد بالا، پروتوتایپ آبجکت child
، دقیقاً آبجکت parent
هست. این رو میشه با کد زیر متوجه شد:
child.__proto__ === parent; // true
توی جاوااسکریپت وقتی دو تا آبجکت رو با ===
مقایسه میکنیم، نتیجه زمانی true
هست که هر دو آبجکت رفرنسهای یکسانی توی حافظه داشته باشن. پس پروتوتایپ child
صرفاً به آدرس parent
اشاره میکنه و مقدار کپی شده نیست. این موضوع رو با این کد هم میشه متوجه شد:
const parent = { lastname: "Doe" } const child = Object.create(parent); alert(child.lastname); // Doe parent.lastname = 'Becker'; alert(child.lastname); // Becker