إتقان وظائف السهم و this في جافا سكريبت

  • إن فهم الفرق بين الدوال الكلاسيكية والأساليب ودوال الأسهم هو المفتاح للتحكم في سلوك `this` في جافا سكريبت.
  • توفر دوال السهم بنية ومفردات موجزة، وهي مثالية لعمليات الاستدعاء وتحويل البيانات دون إنشاء سياق جديد.
  • لا تزال الوظائف التقليدية مطلوبة للمنشئات، والأساليب ذات `this` الديناميكي، والحالات التي يكون فيها كائن الوسائط مطلوبًا.
  • يؤدي اختيار نوع الدالة المناسب في كل حالة إلى تحسين قابلية قراءة وصيانة وقوة كود جافا سكريبت.

إتقان دوال الأسهم و"this" في جافا سكريبت

إذا كنت تبرمج بلغة جافا سكريبت، فستصطدم عاجلاً أم آجلاً بـ دوال الأسهم وهذا الشهيروغالباً ما يكون من غير الواضح على الإطلاق ما يحدث في الخفاء. فبين الدوال والأساليب وردود الاتصال والكائنات التقليدية، من السهل أن يختلط عليك الأمر بسبب السياق، وينتهي بك الأمر إلى تصحيح خطأ يبدو "سحرياً" لساعات.

في السطور التالية، سنقوم بتفكيك كل ذلك "السحر" وسنرى، بهدوء ولكن دون لف ودوران، كيف تعمل الدوال السهمية، وكيف تختلف عن الدوال العادية، وما هي علاقتها الفعلية بهذا؟بالإضافة إلى ذلك، سنلقي نظرة على دور الأساليب والوظائف بشكل عام حتى يكون لديك نظرة عامة كاملة ويمكنك كتابة كود حديث ونظيف وقابل للصيانة.

الأساسيات: ما هي الدالة في جافا سكريبت؟

في لغة جافا سكريبت، الدالة هي في الأساس كتلة برمجية قابلة لإعادة الاستخدام مصممة لأداء مهمة محددةبمجرد تعريفها، يمكنك استدعاؤها عدة مرات كما تريد، بقيم إدخال مختلفة، دون تكرار نفس الكود مرارًا وتكرارًا.

عند تعريف دالة كلاسيكية، فإنك تستخدم الكلمة المفتاحية وظيفة، اسم اختياري وقائمة بالمعلمات بين قوسين. تمثل المعاملات المدخلات، وتمثل القيمة المُعادة المخرجات.عملية جمع عددين عادية تبدو كالتالي:

function suma(a, b) {
  return a + b;
}

let resultado = suma(5, 3);
console.log(resultado); // 8

في هذا الجزء من الكود، الدالة سوما يستقبل البرنامج مُعاملين، أيب، يقوم بالعملية الداخلية ويعيد النتيجة مع عائد أعلىوالتي يمكننا بعد ذلك تخزينها في متغير أو استخدامها مباشرة.

يمكن أن تتضمن الوظائف أيضًا معلمات ذات قيم افتراضيةيُعد هذا مفيدًا جدًا لتجنب الأخطاء عندما يستدعي الكود الدالة بدون جميع الوسائط المتوقعة:

function saludo(nombre = "desconocido") {
  return `¡Hola, ${nombre}!`;
}

console.log(saludo());      // ¡Hola, desconocido!
console.log(saludo("Alice")); // ¡Hola, Alice!

بفضل الإعدادات الافتراضية، تصبح وظيفتك أكثر قوة وتسامحًا مع المكالمات غير المكتملة.مما يوفر عليك عمليات التحقق اليدوية داخل جسم الدالة.

وبعيدًا عن قواعد اللغة، فإن استخدام الدوال بحكمة يجلب التصميم المعياري، وإمكانية إعادة الاستخدام، وسهولة القراءة المحسّنةتقوم بتقسيم المشكلة الكبيرة إلى أجزاء صغيرة يسهل فهمها واختبارها وصيانتها. من الأسهل بكثير اختبار دالة معزولة بدلاً من كتلة ضخمة من التعليمات البرمجية مختلطة مع كل شيء آخر.

الدوال والأساليب العادية وسياقها

قبل الخوض في وظائف الأسهم، من المفيد فهم كيفية عملها. الوظائف التقليدية فيما يتعلق بهذا السياق وما الفرق بين الدوال "المرنة" والأساليب المرتبطة بالكائنات؟

دالة عادية معلنة باستخدام وظيفة له سلوك من هذه الديناميكيةتعتمد قيمة `this` على كيفية استدعاء الدالة، وليس على مكان كتابتها في الكود. إذا استدعيتها كدالة مستقلة، فقد تشير `this` إلى الكائن العام (في الوضع غير الصارم) أو تكون غير مُعرَّفة (في الوضع الصارم). أما إذا استدعيتها كدالة تابعة لكائن، فعادةً ما تشير `this` إلى ذلك الكائن.

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

const persona = {
  nombre: "Laura",
  saludar: function () {
    console.log("Hola, soy " + this.nombre);
  }
};

persona.saludar(); // "Hola, soy Laura" (this => persona)

الفرق الرئيسي بين الوظيفة والطريقة ليس تقنيًا (كلاهما وظائف في جوهرها)، ولكن أين يتم تخزينها وكيف يتم استدعاؤهايتم استدعاء الدوال "المرنة" باسمها، بينما يتم استدعاء الطرق من خلال الكائن، وهذا يؤثر بشكل مباشر على قيمة هذا.

بالإضافة إلى ذلك، يمكن استخدام الوظائف العادية كـ بناة مع جديديؤدي هذا إلى إنشاء نسخ من الكائنات ذات النموذج الأولي المشترك، ويكون الكائن متاحًا لها. الحجج والذي يشمل جميع الوسائط السابقة، حتى لو لم يتم تعريفها بشكل صريح كمعلمات.

دوال السهم: الصيغة الحديثة

مع إصدار ECMAScript 6 (ES6) جاء الدوال السهمية، وتسمى أيضًا الدوال السهميةوالتي توفر طريقة أكثر إيجازًا لكتابة الدوال، خاصة عندما تكون قصيرة أو تستخدم كدوال رد نداء.

أبسط شكل لدالة السهم يستبدل الكلمة وظيفة بواسطة السهم =>وفي كثير من الحالات يسمح بالعودة الضمنية، مما يوفر أيضًا عائد أعلى والمفاتيح عندما يكون الجسم تعبيرًا واحدًا:

const multiplicacion = (x, y) => x * y;

console.log(multiplicacion(4, 5)); // 20

تُعلن هذه الأنواع من الدوال عادةً على النحو التالي: التعبيرات المخزنة في الثوابت أو المتغيراتلأنها مصممة لتكون مجهولة الهوية (ليس لها اسم مناسب مثل الدوال المعلنة الكلاسيكية) ولا يتم استخدامها كإعلانات دوال مرتفعة.

يمكن تلخيص الصيغة العامة على النحو التالي: المعاملات بين قوسين، ثم السهم =>، ثم تعبير أو كتلة من التعليمات البرمجيةإذا كان لديك مُعامل واحد فقط، يمكنك حذف الأقواس؛ أما إذا كان لديك عدة مُعاملات، فهي مطلوبة:

// Un solo parámetro, sin paréntesis
const doble = n => n * 2;

// Varios parámetros, paréntesis obligatorios
const sumar = (a, b) => a + b;

عندما لا يعود المنطق مناسبًا لتعبير واحد وتحتاج إلى عدة عبارات، تستخدم الأقواس المعقوفة وعبارة إرجاع صريحة.تمامًا كما هو الحال في الوظيفة التقليدية:

const sumaCompleja = (a, b) => {
  let resultado = a + b;
  resultado = resultado * 2;
  return resultado;
};

تقبل دوال السهم أيضًا معلمات ذات قيم افتراضيةوهذا يسمح بتحديد قيم أولية واضحة دون الحاجة إلى عمليات فحص داخلية إضافية:

const cuadrado = (lado = 10) => lado * lado;

console.log(cuadrado());   // 100
console.log(cuadrado(5));  // 25

وبما أنها تعمل كتعبيرات، فمن الشائع أن يكون تم تخزين العديد من دوال الأسهم في متغيرات مختلفة لإعادة استخدامها لاحقاً، على سبيل المثال:

const duplicar = n => n * 2;
const triplicar = n => n * 3;

console.log(duplicar(3));  // 6
console.log(triplicar(3)); // 9

الإرجاع الضمني والصياغة العملية

من أهم مزايا دوال الأسهم ما يلي: يتم الإرجاع الضمني عندما يتم اختزال الجسم إلى تعبير واحدوهذا يجعل المهام المتكررة للغاية، مثل تحويل القيم، سلسة للغاية:

const duplicar = n => n * 2;

هذا المثال مكافئ وظيفيًا لكتابة دالة عادية تستخدم العودة ضمن كتلةلكنك بذلك توفر على نفسك عدة كلمات وأسطر من التعليمات البرمجية:

const duplicar = function (n) {
  return n * 2;
};

عندما ترغب في إرجاع كائن حرفي في دالة السهم ذات الإرجاع الضمني، يجب وضع الكائن بين قوسين لمنع تفسير الأقواس المعقوفة على أنها بداية كتلة برمجية:

const obtenerUsuario = () => ({
  nombre: "Laura",
  edad: 28
});

باستخدام هذه الصيغة، تصبح الدوال السهمية أدوات مثالية لكتابة أكواد قصيرة ومعبرة، ويستخدم على نطاق واسع في طرق المصفوفات، والوعود، والبرمجة الوظيفية الخفيفة، ومنطق المكونات في الأطر الحديثة.

هذا في دوال السهم: السياق المعجمي

الفرق الحقيقي بين دالة السهم والدالة الكلاسيكية لا يكمن فقط في الصيغة: بل في كيف يتعاملون مع قيمة هذا؟بينما تحتوي الدوال العادية على متغير "this" ديناميكي يعتمد على اسمها، فإن دوال السهم تحتوي على هذا المعجم.

القول بأن كلمة "هذا" معجمية يعني أن لا تقوم دالة السهم بإنشاء هذا داخليًا خاصًا بهابدلاً من ذلك، يرث هذا الكود قيمة `this` الخاصة بالسياق الذي تم تعريفه فيه. إذا كتبتَ دالة سهمية داخل دالة عادية، فسيكون `this` الخاص بالدالة السهمية هو نفسه الخاص بالدالة الخارجية؛ أما إذا كنتَ ضمن النطاق العام لوحدة نمطية، فإنه يرث ذلك السياق.

يؤثر هذا بشكل مباشر عند استخدام دوال الأسهم كطرق للكائنات. على سبيل المثال، إذا كتبت شيئًا كهذا:

const obj = {
  nombre: "Juan",
  imprimir: () => {
    console.log(this.nombre);
  }
};

obj.imprimir();

في هذا المقتطف البرمجي، لا يشير `this` داخل دالة السهم إلى `obj`بل إلى السياق الخارجي الذي أُنشئ فيه هذا السهم (على سبيل المثال، الكائن العام أو الوحدة النمطية الحالية). والنتيجة المعتادة هي أن الاسم غير مُعرَّف أو لا يُشير إلى القيمة المتوقعة.

أما الإرث المعجمي لهذا، من ناحية أخرى، إنها نعمة عند العمل مع دوال الاستدعاء داخل الدوالبدلاً من الاضطرار إلى القيام بحيل مثل تخزين `this` في متغير وسيط (`var that = this`) أو استخدام `.bind()`، فإن السهم يحافظ بسهولة على `this` من السياق العلوي:

function Contador() {
  this.valor = 0;

  setInterval(() => {
    this.valor++;
    console.log(this.valor);
  }, 1000);
}

new Contador();

في هذا المثال، الدالة التي تم تمريرها إلى setInterval هو سهملذا، ضمن ذلك، يظل `this` هو مثيل العداد، مما يجعل العمل أسهل بكثير ويتجنب الأخطاء النموذجية في السياق.

بالإضافة إلى ذلك، فإن دوال الأسهم لا تُنشئ نسختها الخاصة من وسيطات الكائنلذلك، إذا كنت بحاجة إلى الوصول إلى جميع الوسائط التي تم تمريرها ديناميكيًا، فسيتعين عليك استخدام عامل الراحة (…المعاملات) أو اللجوء إلى الوظيفة الطبيعية حسب الاقتضاء.

النطاق المعجمي والإغلاق باستخدام وظائف الأسهم

ومن النتائج الأخرى لتصميم السهم ما يلي: تشترك في نفس النطاق المعجمي مع سياقها الأصليهذا ملحوظ ليس فقط مع `this`، ولكن أيضًا مع المتغيرات التي يمكنهم الوصول إليها، وهو ما يتناسب تمامًا مع مفهوم الإغلاقات.

فكّر في دالة تُعيد دالة داخلية أخرى. إذا كانت الدالة الداخلية دالة سهمية، ستتمكن من الاستمرار في استخدام المتغيرات المحددة في الدالة الخارجيةحتى لو انتهى تشغيله بالفعل:

const exterior = () => {
  const variableExterna = "Valor exterior";

  return () => {
    console.log(variableExterna);
  };
};

const interna = exterior();
interna(); // "Valor exterior"

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

مقارنة بين الدوال السهمية والدوال العادية

إذا وضعنا دالة كلاسيكية وسهمًا جنبًا إلى جنب، فسنرى عدة الاختلافات ذات الصلة التي تؤثر على كيفية استخدامنا لها في الممارسة اليومية:

  • الصياغة والإيجاز: تُكتب الدالة الطبيعية على النحو التالي: function nombre() {}بينما يكون السهم عادةً const nombre = () => {}في الحالات البسيطة، يكون السهم أقصر وأكثر وضوحاً بشكل واضح.
  • الرفع: إعلانات الدوال التقليدية هي يرفعونلذلك، يمكنك استدعاؤها قبل تعريفها في الكود. الأسهم، كونها تعبيرات مُسندة إلى متغيرات أو ثوابت، لا يمكن استخدامها قبل تعريفها.
  • سياق هذا: تحتوي الدالة الكلاسيكية على `this` ديناميكي يتغير اعتمادًا على كيفية استدعائها؛ أما السهم فيحتوي على `this` معجمي، موروث من السياق الذي تم فيه الإعلان عنه.
  • استخدمه كأداة بناء: يمكن استدعاء الدوال العادية باستخدام جديد لإنشاء الكائنات؛ دوال السهم لا يمكن استخدامهم كبناة.
  • وسائط الكائن: في الوظائف التقليدية لديك الحجج; في الأسهم، هذا الكائن غير موجود، وعادةً ما تُستخدم معلمات الباقي.

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

الاستخدامات الشائعة لدوال الأسهم

في لغة جافا سكريبت الحديثة، يكثر استخدام الدوال السهمية في الاستخدام اليومي، وخاصة في الدوال المستدعاة، وطرق المصفوفات، والتعليمات البرمجية الوظيفيةإنها البديل الطبيعي للوظائف المجهولة التي تستمر مدى الحياة.

ومن الاستخدامات الشائعة جداً تمريرها على أنها الدوال المستدعاة في طرق المصفوفات مثل forEach و map و filter و reduce. يصبح بناء الجملة أقصر بكثير، ومن خلال الوراثة من هذا، فإنها تتناسب بشكل أفضل مع العديد من السيناريوهات:

const nombres = ;

nombres.forEach(nombre => {
  console.log(`Hola ${nombre}`);
});

بالمقارنة مع كتابة نفس الشيء باستخدام دالة، النسخة التي تحتوي على السهم أنظف بكثير. ولا يفقد وضوحه:

.map(function (n) {
  return n * 2;
});

.map(n => n * 2);

عند إجراء تحويلات أكثر تعقيدًا، فإن طرقًا مثل تصفية ورسم الخرائط كما أنهم يستفيدون بشكل واضح من صيغة السهم:

const nums = ;

const pares = nums.filter(n => n % 2 === 0);
const duplicados = nums.map(n => n * 2);

console.log(pares);      // 
console.log(duplicados); // 

تُستخدم الأسهم أيضًا بشكل متكرر في مؤقت أو ردود استدعاء الأحداث...بشرط أن تتناسب طريقة معالجة `this` التي يوفرونها مع احتياجاتك. على سبيل المثال، في دالة `setTimeout`، من الشائع جدًا رؤية ما يلي:

setTimeout(() => {
  console.log("Mensaje con delay");
}, 1000);

في حالة التكرار عبر المصفوفات باستخدام forEach ودوال الأسهميُعد هذا المزيج مناسبًا بشكل خاص لإجراء عمليات بسيطة على كل عنصر دون فقدان الوضوح:

const nombres = ;

nombres.forEach(nombre => console.log("Hola " + nombre));

متى يكون استخدام الدوال السهمية مناسباً ومتى لا يكون كذلك؟

بالنظر إلى كل ما سبق، يبدو أن دوال الأسهم هي الحل لكل شيء، لكن الحقيقة هي أن ليست دائماً الخيار الأفضلهناك حالات محددة يُفضل فيها الاستمرار في أداء الوظائف التقليدية.

تضيء وظائف الأسهم عند الحاجة إليها. الاستدعاءات القصيرة، وتحويلات البيانات، وتركيب الدوال، ووراثة `this` من البيئةفي تلك الحالات، تتجنب كتابة التعليمات البرمجية المتكررة، وتبسط الكود، وتسهل متابعة منطق برنامجك.

ومع ذلك، لا ينبغي استخدامها كدوال إنشاءلأنها لا تعمل مباشرةً مع `new`. إذا كنت تنوي إنشاء أنواع أو فئات أو نماذج أولية مخصصة، فاستمر في استخدام الدوال العادية أو صيغة `class`.

كما أنه ليس من المستحسن الإعلان استخدم أساليب الكائنات مثل السهم إذا كنت تتوقع أن يشير `this` إلى ذلك الكائنلقد رأينا بالفعل أن السهم لا يحدد `this` الخاص به، لذلك لن تكون القيمة هي ما يتوقعه العديد من المطورين عند قراءة الكود، مما يؤدي إلى أخطاء دقيقة.

حتى في أشياء مثل تعتمد بعض معالجات الأحداث أو واجهات برمجة التطبيقات سلوكها على قيمة هذا.قد تكون الدالة العادية أكثر ملاءمة، وذلك تحديداً لأنه في هذه الحالة من المهم أن يتغير هذا الأمر تبعاً لمن يقوم باستدعاء الدالة.

وأخيرًا، إذا كنت بحاجة إلى وصول مرن إلى جميع الوسائط المستلمة عبر الوسائطقد تجد أنه من الطبيعي أكثر استخدام دالة تقليدية، أو إعادة تصميم واجهة الدالة الخاصة بك لاستخدام معلمات REST.

الدوال والأساليب في تصميم تطبيقات جافا سكريبت

بمجرد أن تفهم الاختلافات بين الدوال السهمية، والدوال الكلاسيكية، والأساليبيمكنك الاستفادة منها حقًا في هيكلة تطبيقات جافا سكريبت كاملة، سواء الواجهة الأمامية أو الخلفية.

تُعدّ الدوال "العادية" مصدرًا ممتازًا لـ المهام العامة، وإنشاء الكائنات (المنشئات)، والمنطق الذي ترغب فيه بالتحكم الدقيق في هذاكما أن قدرتها على رفع الملفات يمكن أن تبسط تنظيم التعليمات البرمجية في الملفات الكبيرة إذا قمت بترتيبها بعناية.

أما الأساليب، من جانبها، فتعمل على إجراءات محددة مرتبطة ببيانات كائن مامن المنطقي تمامًا أن يشير `this` إلى الكائن نفسه، لأنهما يجسدان السلوك والحالة معًا. عند تعريف دالة في نموذج أولي أو فئة، من الطبيعي استخدام `function` أو الصيغة المختصرة لدوال الكائنات.

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

إن فهم دور كل نوع من أنواع الدوال، ومعرفة متى تستخدم كل نوع على حدة، وإتقان سلوك `this`، يسمح لك بكتابة كود جافا سكريبت أكثر قوة ونظافة وسهولة في التوسع، متجنباً العديد من الفخاخ اللغوية الكلاسيكية.

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

نصوص المكتب
المادة ذات الصلة:
مقدمة إلى برامج Office النصية لبرنامج Excel Online