درود دوستان! امروز می‌خوایم با یک خاصیت پیشرفته از توابع جاوااسکریپت آشنا بشیم. توی این قسمت می‌خوایم Constructor Functions رو مفصل بررسی کنیم.

توی این قسمت یاد می‌گیریم که:

 

مشکل کجاست؟

فرض کنیم آبجکتی داریم به صورت زیر:

const mario = {
  name: 'Mario',
  age: 4,
  
  talk() {
    return `${this.name} is talking`;
  },

  sleep() {
    return `${this.name} is trying to sleep`;
  },
}

alert(mario.talk());
alert(mario.sleep());

همونطور که می‌بینیم توی آبجکت mario ما ۲ پراپرتی داریم و ۲ متد. حالا فرض کنیم می‌خوایم یک آبجکت مشابه همین آبجکت داشته باشیم. یعنی آبجکتی که دقیقاً همین پراپرتی‌ها و متدها رو داشته باشه ولی با مقدارهای پراپرتی متفاوت:

const emily = {
  <<name: 'Emily'>>,
  <<age: 6>>,
  
  talk() {
    return `${this.name} is talking`;
  },

  sleep() {
    return `${this.name} is trying to sleep`;
  },
}

alert(emily.talk());
alert(emily.sleep());

خب ما اینجا دقیقاً آبجکت mario رو کپی کردیم تا یک آبجکت مشابه داشته باشیم. اگه بخوایم هزار تا دیگه از این آبجکت‌ها داشته باشیم چطور؟ باید همینطوری از آبجکت کپی کنیم؟ این کار منطقی بود تا قبل از اینکه مفهومی به اسم کلاس‌ها معرفی بشن!

 

کلاس چیه؟

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

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

وظیفه یک کلاس اینه که مشخص کنه آبجکت‌ها چه ویژگی‌ها و رفتارهایی داشته باشن. وقتی یک کلاس می‌سازیم، توی اون پراپرتی‌ها و متدهایی رو تعریف می‌کنیم و بدین صورت آبجکت‌هایی که از این کلاس‌ها ساخته میشن، شامل این پراپرتی‌ها و متدها هستن.

توی اکثر زبان‌های شی‌گرایی برای داشتن کلاس ما از روش زیر استفاده می‌کنیم:

class Person {
  // ...
}

اما توی جاوااسکریپت و تا قبل از معرفی شدن ES6، ما از یک روش دیگه برای داشتن کلاس استفاده می‌کردیم به اسم Constructor Function.

 

Constructor Function چیه؟

Constructor Function که به اون توابع سازنده هم گفته میشه، یک راه سنتی برای داشتن کلاس‌ها توی جاوااسکریپت هست.

نحوه ساختن این توابع درست مثل توابع معمولی هست:

function Person(name) {
  this.name = name;
}

همونطور که می‌بینیم یک تابع عادی نوشتیم که اسمش Person هست. این تابع یک ورودی می‌گیره که اون رو توی تابع نسبت دادیم به this.name. با این روش، آبجکت‌هایی که بعداً می‌سازیم همگی یک پراپرتی دارن به اسم name.

به چیزی که نوشتیم می‌گیم طرح و الگو. یک طرح و الگو برای آبجکت‌هایی که می‌خوایم بسازیم.
 

چطوری آبجکت بسازیم؟

برای ساختن آبجکت از Constructor Function ها کافیه اسم تابع رو بنویسیم و قبل از اون از کلمه‌کلیدی new مثل کد زیر استفاده کنیم:

const mario = new Person('Mario');

تابع Person یک ورودی می‌گرفت به اسم name که موقع صدا زدن تابع باید اون رو پاس می‌دادیم. الان مقدار متغیر mario یک آبجکت هست که یک پراپرتی به اسم name با مقدار Mario داره:

function Person(name) {
  this.name = name;
}

const mario = new Person('Mario');

alert(mario.name); // Mario

الان می‌تونیم به همین صورت بی‌نهایت آبجکت داشته باشیم که همگی توی خودشون یک پراپرتی به اسم name و با مقداری که توی ورودی به تابع پاس دادیم دارن:

function Person(name) {
  this.name = name;
}

const mario = new Person('Mario');
const emily = new Person('Emily');
const sarah = new Person('Sarah');
const david = new Person('David');

حالا بیاین تابع Person رو بر اساس مثالی که ابتدای کد داشتیم کامل‌تر کنیم و بقیه پراپرتی‌ها و متدها رو هم اضافه کنیم:

function Person(name, age) {
  this.name = name;
  this.age = age;

  this.talk = function () {
    return `${this.name} is talking`;
  };

  this.sleep = function () {
    return `${this.name} is trying to sleep`;    
  }
}

برای داشتن متد توی این توابع، کافیه یک پراپرتی بسازیم که مقدار اون یک تابع هست. همچنین برای دسترسی به بقیه پراپرتی‌ها توی این توابع، مثل خط‌های ۶ و ۱۰ از کلمه‌کلیدی this استفاده می‌کنیم.

حالا همه آبجکت‌هایی که می‌سازیم دو پراپرتی به اسم‌های name و age و دو متد به اسم‌های talk و sleep دارن:

function Person(name, age) {
  this.name = name;
  this.age = age;

  this.talk = function () {
    return `${this.name} is talking`;
  };

  this.sleep = function () {
    return `${this.name} is trying to sleep`;    
  }
}

const mario = new Person('Mario', 4);
alert(mario.talk());  // Mario is talking
alert(mario.sleep()); // Mario is trying to sleep

const emily = new Person('Emily', 6);
alert(emily.talk());  // Emily is talking
alert(emily.sleep()); // Emily is trying to sleep

 

یکی از استانداردهای درست‌نویسی توی نام‌گذاری توابع سازنده اینه که اسم تابع رو با حرف اول بزرگ بنویسیم تا به خواننده بگیم که این یک تابع سازنده هست و با بقیه توابع فرق می‌کنه:

function Person { }
function <<<person>>> { }

 

فواید Constructor Function چیه؟ 🤔

اگه اول راه یادگیری و برنامه‌نویسی هستین، شاید کاربرد این توابع کم‌رنگ باشه. اما خوبه که بدونیم با Constructor Function ها:

۱. همونطور که دیدیم حجم کدنویسی ما فوق‌العاده پایین‌تر میاد. دیگه لازم نیست برای هر آبجکتی که می‌خوایم بسازیم به صورت دستی پراپرتی و متد تعریف کنیم. کافیه اونها رو توی تابع تعریف کنیم تا توی همه آبجکت‌ها قرار بگیرن.

۲. اگه بخوایم توی آبجکت‌هایی که به صورت دستی و بدون Constructor Function ها ساخته شدن، تغییری اعمال کنیم (مثلاً پراپرتی اضافه کنیم و یا متدها رو دستکاری کنیم) باید این تغییرات رو توی تک‌تک آبجکت‌ها اعمال کنیم. اما با Constructor Function ها فقط کافیه خود تابع رو دستکاری کنیم تا تغییرات به صورت خودکار توی آبجکت‌ها اعمال بشن.

 

خب دوستان امیدوارم از مباحثی که بررسی کردیم استفاده کرده باشین. بالاتر به این نکته اشاره کردیم که Constructor Function ها یک روش سنتی برای داشتن کلاس‌ها توی جاوااسکریپت به حساب میان و با معرفی شدن ES6 این کار رو با Class ها انجام می‌دیم. کلاس‌ها کاربردی کاملاً مشابه با این توابع دارن که با اونها توی قسمت‌های بعدی آشنا می‌شیم 🖐️