اذهب إلى المحتوى

نظرة تفصيلية على الدوال السهمية Arrow functions في جافاسكربت


صفا الفليج

سبق وأن مررنا على الدوال السهمية مرورًا سريعًا في مقال الدوال في الكائنات واستعمالها this ( وننصحك بالرجوع إليه وقراءته إن لم تكن قد قرأته مسبقًا) وتعرفنا على كيفية استخدامها استخدامًا أساسيًا وسنتعمق الآن فيها تعمقًا أكبر.

لو ظننت الدوال السهمية هي طريقة مختصرة لكتابة الشيفرات القصيرة، فأنت مخطئ، إذ لهذه الدوال مزايا تختلف عن غيرها وتفيدنا جدًا.

كثيرًا ما نواجه المواقف (في جافاسكربت بالتحديد) التي نريد أن نكتب فيها دالة صغيرة وننفّذها في مكان آخر.

مثال:

  • ‎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) {
      // ‫خطأ: تعذّرت قراءة الخاصية 'title' لغير المعرّف 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


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...