متدها و Accessor ها در اشیاء جاوا اسکریپت

25 اسفند 1397
Advanced-Javascript-accessors-methods

با سلام خدمت شما عزیزان و همراهان همیشگی روکسو، در این جلسه قصد داریم در رابطه با دو وجه متفاوت اشیاء جاوا اسکریپتی صحبت کنیم؛ متدها و Accessor ها.

متدهای اشیاء در جاوا اسکریپت

متدها در جاوا اسکریپت اعمالی هستند که روی یک شیء انجام می شوند اما object method (یعنی متدهایی که متعلق به اشیا هستند) یکی از خصوصیات شیء است که دارای تعریف یک تابع است. به زبان ساده تر بگویم، متدهای اشیاء در جاوا اسکریپت همان توابعی هستند که درون اشیاء گذاشته شده اند تا اعمال خاصی را انجام دهند. مثال زیر را ببینید:

var person = {
  firstName: "John",
  lastName : "Doe",
  id       : 5566,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

در خصوصیت fullName، تعریف یک تابع را داریم. به این تعریف تابع یک متد می گوییم.

کلیدواژه ی this

در تعریف یک تابع، کلیدواژه ی this به صاحب آن تابع برمیگردد بنابراین در مثال بالا this به شیء person برمیگردد چرا که صاحب خصوصیت fullName و طبیعتا آن تابع است. پس می توان گفت this.firstName به معنی خصوصیتِ firstName از این شیء است. من توضیح بیشتری در مورد این کلیدواژه نمی دهم چرا که در دوره ی قبلی (دوره ی مقدماتی) در مورد آن مفصلا صحبت کردیم. برای مطالعه ی بیشتر به مقاله ی زیر رجوع کنید:

دسترسی به متد اشیاء

برای دسترسی به متدهای یک شیء از ساختار زیر استفاده می کنیم:

objectName.methodName()

نکته: طبق مثال بالا به ()fullName می گوییم متد و به fullName میگوییم خصوصیت (property)! بنابراین خصوصیتی به نام fullName داریم که با قرار دادن پرانتز جلوی آن صدا زده می شود و متدی که درونش دارد را اجرا می کند.

بیایید به چند مثال نگاه کنیم:

<!DOCTYPE html>
<html>
<body>

<p>Creating and using an object method.</p>

<p>A method is actually a function definition stored as a property value.</p>

<p id="demo"></p>

<script>
var person = {
  firstName: "John",
  lastName : "Doe",
  id     : 5566,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

document.getElementById("demo").innerHTML = person.fullName();
</script>
</body>
</html>

همانطور که حدس می زدیم خروجی این کد عبارت "John Doe" خواهد بود.

اما اگر پرانتز ها را روبروی person.fullName قرار ندهیم چه می شود؟ به طور مثال کد بالا را به شکل زیر ویرایش کنیم:

<script>
var person = {
  firstName: "John",
  lastName : "Doe",
  id     : 5566,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

document.getElementById("demo").innerHTML = person.fullName;
</script>

در این حالت خروجی ما تعریفِ خود تابع (متد) خواهد بود!

function() { return this.firstName + " " + this.lastName; }

اگر دوست دارید خروجی این دستور را خودتان مشاهده کنید، روی این لینک کلیک کنید.

سوال: آیا می توانیم متدهایی را به یک شیء اضافه کنیم؟

پاسخ: بله! این کار اصلا سخت نیست و مانند اضافه کردن خصوصیات (property) به شیء است. تنها تفاوت در این است که به جای مقداری معین، تعریف یک تابع را به آن می دهید. به مثال زیر توجه کنید:

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>
var person = {
  firstName: "John",
  lastName : "Doe",
  id     : 5566,
};
person.name = function() {
  return this.firstName + " " + this.lastName;
};

document.getElementById("demo").innerHTML =
"My father is " + person.name(); 
</script>

</body>
</html>

نمایش خروجی این کد در JSBin

متدهای از پیش ساخته شده

در جاوا اسکریپت متدهایی داریم که از قبل توسط خود توسعه دهندگان این زبان ساخته شده اند. من یک مثال از آن را برای شما آورده ام تا طرز کار آن ها را ببینید:

این مثال از متد ()toUpperCase استفاده می کند تا رشته ی متنی را به رشته ای با حروف بزرگ تبدیل کند:

var message = "Hello world!";
var x = message.toUpperCase();

با اجرای این دستور رشته ی اولیه ی ما که "!Hello world" است تبدیل به "!HELLO WORLD" می شود.

Accessor ها در جاوا اسکریپت

Accessor در لغت به معنی دسترسی گیرنده یا دسترسی دهنده است. ممکن است با خودتان بگویید من به زبان جاوا اسکریپت مسلط هستم اما چیزی به نام Accessor نمیشناسم! دلیلش این است که کمتر کسی از کلمه ی Accessor استفاده می کند چرا که این واژه کلی است. در واقع به Setter ها و Getter ها به صورت یکجا می گوییم Accessor ها.

در واقع Accessor ها در سال 2009 و با ECMAScript 5 معرفی شدند و به شما اجازه می دهند به برخی از خصوصیات اشیاء دسترسی داشته باشید و به همین دلیل نامشان دسترسی دهنده است (به شما دسترسی می دهند).

کلیدواژه ی Get

قبل از هر چیز باید بدانید که get به فارسی معنی «گرفتن» دارد و در اشیاء جاوا اسکریپت معنی «بگیر» می‌دهد. برای درک بهتر این کلیدواژه بهتر است بدون مقدمه چینی مستقیما به سراغ مثال هایش برویم.

در مثال زیر از خصوصیتی به نام lang استفاده می کنیم تا مقدارِ خصوصیتِ language را get  کنیم، یعنی دریافت کنیم:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Getters and Setters</h2>

<p>This example uses a lang property to get the value of the language property.</p>

<p id="demo"></p>

<script>
// Create an object:
var person = {
  firstName: "John",
  lastName : "Doe",
  language : "en",
  get lang() {
    return this.language;
  }
};
// Display data from the object using a getter:
document.getElementById("demo").innerHTML = person.lang;
</script>

</body>
</html>

نمایش خروجی این کد در JSBin

خروجی این کد en خواهد بود اما چطور؟ بگذارید مرحله مرحله برایتان توضیح دهم:

  • ما یک شیء به نام person داریم.
  • این شیء دارای خصوصیاتی (property) است (مانند firstName، lastName، language و ...).
  • ما با استفاده از کلیدواژه ی get یک خصوصیت به نام lang را می سازیم (که در واقع یک تابع است).
  • lang به ما مقدارِ خصوصیتِ language (یعنی زبان) را برمیگرداند.
  • خروجی آن نیز en (مخفف English - به معنای انگلیسی) بود.

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

var person = {
  firstName: "John",
  lastName : "Doe",
  language : "",
  set lang(lang) {
    this.language = lang;
  }
};

// یک خصوصیت را برای شیء تعیین می کند
person.lang = "en";

// داده را از شیء گرفته و نمایش می دهد
document.getElementById("demo").innerHTML = person.language;

بله درست حدس زدید، با استفاده از خصوصیت lang ، مقدار language را set (یعنی «تعیین») کرده ایم. در این حالت نیز خروجی en خواهد بود.

تفاوت Accessor ها و متدها

به نظر شما تفاوت دو مثال زیر چیست؟

var person = {
  firstName: "John",
  lastName : "Doe",
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};

document.getElementById("demo").innerHTML = person.fullName();
var person = {
  firstName: "John",
  lastName : "Doe",
  get fullName() {
    return this.firstName + " " + this.lastName;
  }
};

document.getElementById("demo").innerHTML = person.fullName;

ما در هر دو مثال به خصوصیت fullName دسترسی پیدا می کنیم اما در مثال اول این کار از طریق یک تابع صورت می گیرد (()person.fullName) و در مثال دوم از طریق یک property یا خصوصیت (person.fullName). تفاوتی بین این دو روش نیست به غیر از اینکه نوشتن کد ها در روش دوم کمی ساده تر است.

نکته: شما می توانید در این مثال ها از روش زنجیره سازی متدها نیز استفاده کنید. به مثال زیر دقت کنید:

var person = {
  firstName: "John",
  lastName : "Doe",
  language : "en",
  get lang() {
    return this.language.toUpperCase();
  }
};

document.getElementById("demo").innerHTML = person.lang;

در این مثال در هنگام تعریف lang از متد toUpperCase استفاده کرده ایم بنابراین همیشه خروجی آن با حروف بزرگ خواهد بود و نیازی نیست هر دفعه این دستور را روی خروجی اعمال کنیم.

این مسئله تفاوتی برای setter ها ندارد:

set lang(lang) {
    this.language = lang.toUpperCase();
  }

نکته: ممکن است نام دستور ()Object.defineProperty را شنیده باشید. این دستور می تواند Setter یا Getter های مورد نظر شما را بسازد. به مثال زیر دقت کنید:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Getters and Setters</h2>

<p>Perfect for creating counters:</p>

<p id="demo"></p>

<script>
// تعریف کردن شیء اولیه
var obj = {counter : 0};

// Setters و Getters تعریف کردن 
Object.defineProperty(obj, "reset", {
  get : function () {this.counter = 0;}
});
Object.defineProperty(obj, "increment", {
  get : function () {this.counter++;}
});
Object.defineProperty(obj, "decrement", {
  get : function () {this.counter--;}
});
Object.defineProperty(obj, "add", {
  set : function (value) {this.counter += value;}
});
Object.defineProperty(obj, "subtract", {
  set : function (value) {this.counter -= value;}
});

// تست کردن کد ها
obj.reset;
obj.add = 5;
obj.subtract = 1;
obj.increment;
obj.decrement;
document.getElementById("demo").innerHTML = obj.counter;
</script>

</body>
</html>

نمایش خروجی این کد در JSBin

در مثال واضح است که این دستور کار خاصی انجام نمی دهد بلکه روش دیگری برای تعریف setter ها و getter ها است.

امیدوارم این قسمت برای شما مفید واقع شده باشد.

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

دیدگاه‌های شما (2 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

سهیل
02 دی 1399
واقعا بهترین توضیحی بود که خوندم کاملا سوال هایی که تو ذهن خواننده میاد داخل متن پاسخ داده شده خداقوت

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

seyed ali
17 آبان 1399
ئاقعا عالی توضیح میدید

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.