لنرى الدوال السهمية مرّة أخرى.
لو ظننت الدوال السهمية هي طريقة مختصرة لكتابة الشيفرات القصيرة، فأنت مخطئ، إذ لهذه الدوال مزايا تختلف عن غيرها وتفيدنا جدًا.
كثيرًا ما نواجه المواقف (في جافا سكريبت بالتحديد) التي نريد أن نكتب فيها دالة صغيرة وننفّذها في مكان آخر.
مثال:
arr.forEaoch(func)
: تُنفّذforEach
الدالةfunc
لكلّ عنصر في المصفوفة.setTimeut(func)
: يُنفّذ المجدول الداخلي في البيئة دالةfunc
.- …وغيرها وغيرها.
هذا هو جوهر اللغة، أن نصنع دالة في مكان ونمرّرها إلى مكان آخر.
وفي هذه الدوال عادةً ما لا نريد أن نترك سياقها الحالي، وهنا تأتي الفائدة المخفية للدوال السهمية.
ليس للدوال السهمية مفهوم الأنا this
كما نذكر من فصل «دوال الكائنات، this» فليس في الدوال السهمية مفهوم this
، ولو حاولت الوصول إلى قيمة this
فستأخذها الدالة من الخارج.
فمثلًا يمكننا استعمالها للمرور على العناصر داخل تابِع للكائن:
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
group.showList();
استعملنا هنا في forEach
الدالة السهمية، وقيمة this.title
فيها هي تمامًا القيمة التي يراها التابِع الخارجي showList
، أي group.title
.
لو استعملنا هنا الدوال العادية فسنواجه خطأً:
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(function(student) {
// Error: Cannot read property 'title' of undefined
alert(this.title + ': ' + student);
});
}
};
group.showList();
سبب هذا الخطأ هو أنّ التابِع forEach
يشغّل الدوال بتمرير this=undefined
مبدئيًا، وبذلك تحاول الشيفرة الوصول إلى undefined.title
.
ليس لهذا أيّ تأثير على الدوال السهمية إذ ليس لها this
أساسًا.
لا يمكن تشغيل الدوال السهمية باستعمال new
بطبيعة الحال فدون this
تواجه حدًّا آخر: لا يمكنك استعمال الدوال السهمية على أنّها مُنشِئات دوال، أي لا يمكنك استدعاءها باستعمال new
.
الدوال السهمية والربطات
هناك فرق بسيط بين الدالة السهمية =>
والدالة العادية التي نستدعيها باستعمال .bind(this)
:
- يُنشئ التابِع
.bind(this)
«نسخة مربوطة» من تلك الدالة. - لا يصنع السهم
=>
أيّ نوع من الربطات. الدالة ليس فيهاthis
، فقط. يبحث المحرّك عن قيمةthis
كما يبحث عن أيّ قيمة متغير آخر: في البيئة المُعجمية الخارجية للدالة السهمية.
ليس للدوال السهمية «مُعاملات»
كما وأنّ الدوال السهمية ليس فيها متغير مُعاملات arguments
.
وهذا أمر رائع حين نتعامل مع المُزخرِفات إذ نُمرّر الاستدعاء حاملًا قيمة this
الحالية مع المُعاملات arguments
.
فمثلًا هنا تأخذ defer(f, ms)
دالةً وتُعيد غِلافًا (Wrapper) عليها تُؤجّل الاستدعاء بالمليثوان ms
الممرّرة:
function defer(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms);
};
}
function sayHi(who) {
alert('Hello, ' + who);
}
let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // Hello, 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
… لم نشرح ذلك بعد ولكنّا سنفعل في الفصل «وراثة الأصناف».
ليس فيها هذا كله لأنّ الغرض منها كتابة شيفرات قصيرة ليس لها سياق تعتمد عليه بل سياقًا تأخذه، وهنا حين «تتألّق» هذه الدوال. ترجمة -وبتصرف- للفصل Arrow functions revisited من كتاب The JavaScript language