بیایید دوباره سری به تابعهای کمانی بزنیم.
تابعهای کمانی فقط «کوتاهنویسی» برای نوشتن چیزهای کوچک نیستند. آنها ویژگیهایی خاص و کاربردی دارند.
جاوااسکریپت پر از موقعیتهایی است که ما نیاز به نوشتن یک تابع کوچک داریم تا جایی دیگر اجرا شود.
برایی مثال:
arr.forEach(func)–funcبرای هر المان آرایه توسطforEachاجرا میشود.setTimeout(func)–funcتوسط زمانبند درونی اجرا میشود.- …و چیزهای دیگر
اینکه تابعی را بسازیم و آن را جایی دیگر پاس دهیم در ذات جاوااسکریپت است.
و معمولا ما نمیخواهیم زمینه کنونی را درون چنین تابعهایی از دست دهیم. اینجا جایی است که تابعهای کمانی بدرد میخورند.
تابعهای کمانی “this” ندارند
همانطور که از فصل متدهای شیء، "this" به یاد داریم، تابعهای کمانی this ندارند. اگر به this دسترسی پیدا کنیم، از بیرون دریافت میشود.
برای مثال، ما میتوانیم از آن برای حلقه زدن درون یک متد شیء استفاده کنیم:
let group = {
title: "گروه ما",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
group.showList();
اینجا درون forEach، تابع کمانی استفاده شده است پس this.title درون آن انگار دقیقا درون متد بیرونی showList است. یعنی: group.title.
اگر ما یک تابع «معمولی» استفاده میکردیم، یک ارور دریافت میکردیم:
let group = {
title: "گروه ما",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(function(student) {
// را خواند undefined از 'title' ارور: نمیتوان ویژگی
alert(this.title + ': ' + student);
});
}
};
group.showList();
به دلیل اینکه به طور پیشفرض forEach با this=undefined تابع را اجرا میکند ارور ایجاد میشود پس سعی میشود که undefined.title دریافت شود.
این موضوع روی تابعهای کمانی تاثیری ندارد چون آنها this ندارند.
new اجرا شوندنداشتن this به طور طبیعی به معنی محدودیت دیگری هم هست: تابعهای کمانی نمیتوانند به عنوان سازنده استفاده شوند. آنها نمیتوانند با new فراخوانی شوند.
یک تفاوت جزئی بین یک تابع کمانی <= و یک تابع معمولی که با .bind(this) فراخوانی شده وجود دارد:
.bind(this)یک «نسخه پیوند زده شده» از تابع را میسازد.- کمان
<=چیزی را پیوند نمیزند. تابع حقیقتاthisندارد. جستوجویthisدرست مانند جستوجوی یک متغیر معمولی انجام میشود: در محیط لغوی بیرونی.
تابعهای کمانی “arguments” ندارند
تابعهای کمانی متغیر arguments هم ندارند.
زمانی که در دکوراتور ما باید یک فراخوانی را با this کنونی و arguments ارسال کنیم عالی است.
برای مثال، defer(f, ms) یک تابع دریافت میکند و دربرگیرندهای دور آن که فراخوانی را به اندازه ms میلیثانیه تاخیر میاندازد را برمیگرداند:
function defer(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms);
};
}
function sayHi(who) {
alert('سلام، ' + who);
}
let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // John ،بعد از دو ثانیه: سلام
کد یکسان بدون تابع کمانی میتواند اینگونه باشد:
function defer(f, ms) {
return function(...args) {
let ctx = this;
setTimeout(function() {
return f.apply(ctx, args);
}, ms);
};
}
اینجا ما باید متغیرهای اضافی args و ctx را ایجاد میکردیم تا تابع درون setTimeout بتواند آنها را دریافت کند.
خلاصه
تابعهای کمانی:
- دارای
thisنیستند - دارای
argumentsنیستند - نمیتوانند همراه با
newفراخوانی شوند - همچنین آنها
superندارند اما هنوز آن را نخواندهایم. در فصل وراثت کلاس آن را خواهیم خواند
به دلیل اینکه آنها برای قطعههای کوتاهی از کد در نظر گرفته شدهاند که «زمینه(context)» خودشان را ندارند و در زمینه کنونی کار میکنند. و آنها واقعا در این مورد استفاده میدرخشند.
نظرات
<code>استفاده کنید، برای چندین خط – کد را درون تگ<pre>قرار دهید، برای بیش از ده خط کد – از یک جعبهٔ شنی استفاده کنید. (plnkr، jsbin، codepen…)