مقدمه

کلاس‌ها از ES6 به جاوااسکریپت اضافه شدند و کار با ساختارهای شی‌گرا را بسیار ساده‌تر و حرفه‌ای‌تر کردند. با کلاس‌ها می‌توانید قالب مشخصی برای اشیا ایجاد کنید و همزمان داده (property) و رفتار (method) را در یک ساختار منسجم تعریف کنید. کلاس (Class) یک الگو برای ساخت اشیا (object) است. هر کلاس مجموعه‌ای از پراپرتی‌ها و متدها را تعریف می‌کند و می‌توان از آن بارها شیء جدید ساخت. این ویژگی پایه‌ی برنامه‌نویسی شی‌گرا را در جاوااسکریپت تشکیل می‌دهد.

شی‌گرایی در جاوااسکریپت

در جاوااسکریپت، همه چیز تقریباً یک شیء است. حتی توابع هم اشیاء هستند! شی‌گرایی (OOP) یعنی بتوانیم داده‌ها و رفتارها را در قالب یک ساختار منسجم (کلاس) تعریف کنیم و از آن بارها نمونه بسازیم. این کار باعث می‌شود کدهایتان مرتب‌تر، قابل فهم‌تر و قابل توسعه‌تر شوند. قبل از ES6، برای ساخت اشیاء معمولاً از توابع سازنده (constructor functions) و prototype استفاده می‌شد. اما با معرفی کلاس‌ها، تعریف و استفاده از ساختارهای شی‌گرا بسیار ساده‌تر و شفاف‌تر شد.

نقش پروتوتایپ

در جاوااسکریپت، هر شیء یک زنجیره پروتوتایپ دارد که به آن اجازه می‌دهد ویژگی‌ها و متدها را از شیء والد خود به ارث ببرد. قبل از معرفی کلاس‌ها، متدها معمولاً روی شیء prototype تابع سازنده تعریف می‌شدند تا همه نمونه‌ها به آن‌ها دسترسی داشته باشند و حافظه کمتری مصرف شود. با استفاده از کلاس‌ها، این کار به صورت خودکار انجام می‌شود و متدهایی که داخل کلاس تعریف می‌کنید، به صورت اشتراکی روی prototype قرار می‌گیرند. بنابراین همه نمونه‌های ساخته‌شده از یک کلاس، به متدهای تعریف‌شده در کلاس (در واقع prototype) دسترسی دارند، اما هر نمونه داده‌های مخصوص به خود را دارد.

آیا هنوز باید راجع به پروتوتایپ بدانیم؟

بله! حتی با وجود کلاس‌ها، دانستن مفهوم پروتوتایپ همچنان مهم است. زیرا کلاس‌ها در واقع یک لایه سینتکس ساده‌تر روی همان سیستم پروتوتایپ هستند. اگر بخواهید رفتارهای پیشرفته‌تری مثل افزودن متد به همه نمونه‌ها بعد از تعریف کلاس، یا درک نحوه کار ارث‌بری و زنجیره prototype را داشته باشید، باید با این مفهوم آشنا باشید. اما برای اکثر استفاده‌های روزمره، کار با کلاس‌ها کافی است و نیازی به دستکاری مستقیم prototype نخواهید داشت.

سینتکس تعریف کلاس

برای تعریف یک کلاس کافی است از کلمه کلیدی class استفاده کنید. معمولاً یک متد ویژه به نام constructor در کلاس‌ها وجود دارد که هنگام نمونه‌سازی شیء جدید اجرا می‌شود و مقداردهی اولیه انجام می‌دهد.

در مثال زیر یک کلاس ساده به نام Person تعریف می‌شود که دارای یک پراپرتی به نام name و یک متد به نام greet است.

Copy Icon JAVASCRIPT
class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    console.log("Hello " + this.name);
  }
}
let user = new Person("ali");
user.greet(); // Hello ali

در اینجا متد greet با استفاده از this.name نام هر شخص را نمایش می‌دهد. هر بار که نمونه جدیدی از کلاس ساخته می‌شود، مقدار name مخصوص به همان نمونه ذخیره می‌شود و متد greet برای هر نمونه خروجی متفاوتی خواهد داشت.

کلاس Person فقط یک پراپرتی و یک متد دارد اما محدودیتی در این مورد وجود ندارد و می‌ٔتوانیم عر تعداد پراپرتی و متد دیگر به این کلاس اضافه کنیم.

ایجاد نمونه (Instance) و استفاده از this

همانطور که در مثال بالا هم دیدیم، با عملگر new می‌توانید هر چند بار که بخواهید نمونه‌ای جدید از کلاس بسازید. هر نمونه داده‌های مخصوص به خود را دارد و از متدهای کلاس استفاده می‌کند. کلیدواژه this در متدهای کلاس همواره به نمونه فعلی اشاره دارد.

مثال زیر دو نمونه مستقل از کلاس Person می‌سازد.

Copy Icon JAVASCRIPT
let ali = new Person("ali");
let sara = new Person("sara");
ali.greet();  // Hello ali
sara.greet(); // Hello sara

در اینجا تابع constructor که سازنده‌ی کلاس است، هنگام ساخت هر نمونه جدید از کلاس اجرا می‌شود و مقدار پراپرتی name را برای همان نمونه تنظیم می‌کند. همچنین متد greet با استفاده از this.name، نام مربوط به هر نمونه را نمایش می‌دهد. بنابراین هر شیء ساخته‌شده از کلاس Person داده‌های مخصوص به خود را دارد و متدها را به صورت مستقل اجرا می‌کند.

نقش تابع سازنده‌ی کلاس

تابع سازنده یا همان constructor در کلاس‌ها وظیفه مقداردهی اولیه به پراپرتی‌های هر نمونه را دارد. هر بار که با new یک شیء جدید از کلاس می‌سازید، این تابع به طور خودکار اجرا می‌شود و می‌توانید مقادیر اولیه پراپرتی‌ها را تعیین کنید. اگر تابع سازنده را تعریف نکنید، جاوااسکریپت یک سازنده پیش‌فرض قرار می‌دهد که هیچ کاری انجام نمی‌دهد.

اجازه دهید کلاس Person را طوری ویرایش کنیم که علاوه بر name، سن (age) هر شخص را هم نگه دارد و به تبع این امر، سازنده را طوری تغییر دهیم که دو پارامتر داشته باشد.

Copy Icon JAVASCRIPT
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    greet() {
        console.log("Hello " + this.name + ", age: " + this.age);
    }
}

let user = new Person("ali", 22);
user.greet(); // Hello ali, age: 22
                        

در این مثال، سازنده کلاس دو پارامتر name و age می‌گیرد و هر دو را به عنوان پراپرتی روی نمونه ذخیره می‌کند. حالا هر نمونه از کلاس Person هم نام و هم سن مخصوص به خود را دارد.

کلاس‌ها پایه برنامه‌نویسی شی‌گرا را در جاوااسکریپت تشکیل می‌دهند و به ما امکان می‌دهند که داده و منطق را در کنار هم به شکلی ساختارمند تعریف کنیم و کدهای مقیاس‌پذیر، قابل توسعه و قابل نگهداری بسازیم. به کمک کلاس‌ها می‌توانیم ویژگی‌های مشترک را در قالب پراپرتی و منطق مرتبط با هر شیء را در قالب متد در یک کلاس پیاده‌سازی کنیم و این امر توسعه و نگهداری پروژه را خیلی ساده‌تر می‌کند. بحث در مورد شی‌گرایی را در درس بعد با پرداختن به موضوع مهم وراثت پی می‌ٔگیریم.