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

صياغة الدالة الجديدة new Function في جافاسكربت


صفا الفليج

توجد (أيضًا) طريقة أخرى لإنشاء الدوال. صحيح هي نادرة الاستعمال ولكن لا مفرّ منها في حالات معيّنة.

الصياغة

إليك صياغة إنشاء الدالة:

let func = new Function ([arg1, arg2, ...argN], functionBody);

نصنع الدالة بالوُسطاء ‎arg1...argN‎ ونمرّر متنها ‎functionBody‎.

«هات الشيفرة وقلّل ثرثرتك»… صحيح، هذا أسهل. إليك الدالة وفيها وسيطين اثنين:

let sum = new Function('a', 'b', 'return a + b');

alert( sum(1, 2) ); // 3

وهنا دالة بلا وُسطاء فيها متنها فقط:

let sayHi = new Function('alert("Hello")');

sayHi(); // Hello

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

ألزمتنا التصريحات السابقة كلها - ألزمتنا نحن المطوّرين أن نكتب شيفرة الدالة في السكربت.

ولكن صياغة ‎new Function‎ تسمح لنا بأن نحوّل أيّ سلسلة نصية لتصير دالة. فمثلًا يمكن أن نستلم دالة جديدة من أحد الخواديم وننفّذها:

let str = ... نستلم الشيفرة ديناميكيًا من الخادوم ...

let func = new Function(str);
func();

لا نستعمل هذه إلا في حالات خاصّة، مثل لو استلمنا الشيفرة من الخادوم أو صنعنا الدالة ديناميكًا من قالب (في تطبيقات الوِب المعقّدة).

المنغلقات

عادةً ما تتذكّر الدالة مكان ولادتها في الخاصية المميّزة ‎[[Environment]]‎، فتُشير إلى البيئة المُعجمية حين صُنعت الدالة (شرحنا هذا في فصل «المُنغِلقات»).

ولكن حين نصنع الدالة باستعمال ‎new Function‎ فتُضبط خاصية ‎[[Environment]]‎ على البيئة المُعجمية العمومية لا الحالية.

أي أنّ هذه الدوال لا يمكن أن ترى المتغيرات الخارجية بل تلك العمومية فقط.

function getFunc() {
  let value = "test";

  let func = new Function('alert(value)');

  return func;
}

getFunc()(); // ‫خطأ: value غير معرّف

وازن بين هذا والسلوك الطبيعي:

function getFunc() {
  let value = "test";

  let func = function() { alert(value); };

  return func;
}

getFunc()(); // ‫«test»، من بيئة getFunc المُعجمية

صحيح أنّ الميزة الخاصة للصياغة ‎new Function‎ غريبة بعض الشيء، ولكنها عمليًا مفيدة جدًا.

تخيّل الآن بأنّنا صنعنا دالة من سلسلة نصية. شيفرة هذه الدالة ليست معروفة ونحن نكتب السكربت (ولهذا لم نستعمل الدوال العادية)، بل ستكون معروفة حين تنفيذه. كما أسلفنا يمكن أن نستلم الدالة من الخادوم أو أيّ مكان آخر.

الآن، على دالتنا هذه التفاعل مع السكربت الرئيس.

لكن ماذا لو أمكن لها أن ترى المتغيرات الخارجية؟

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

فمثلًا لو كان في الدالة ‎let userName‎ فيستبدلها المُصغِّر إلى ‎let a‎ (أو أيّ حرف آخر لو هناك من أخذ الاسم)، وينفّذ هذا في كلّ مكان آخر. عادةً لا يضرّ ذلك إذ أنّ المتغير محلي ولا يمكن لما خارج الدالة رؤيته، بينما يستبدل المُصغِّر كلّ مرة يرد فيها المتغير داخل الدالة. هذه الأدوات ذكية فهي تحلّل بنية الشيفرة لألا تُعطبها، وليست كأدوات البحث والاستبدال الهمجية.

لذا لو أرادت ‎new Function‎ أن تستعمل المتغيرات الخارجية فلن تعرف بوجود ‎userName‎ الذي تغيّر اسمه.

لو أمكن للدوال ‎new Function‎ أن ترى المتغيرات الخارجية لكانت ستواجه مشاكل جمّة مع المُصغِّرات.

كما وأنّ الشيفرات من هذا النوع ستكون سيّئة من حيث البنية وعُرضة للأخطاء والمشاكل.

لو أردت تمرير شيء للدالة ‎new Function‎ فعليك استعمال مُعاملاتها.

ملخص

الصياغة:

let func = new Function ([arg1, arg2, ...argN], functionBody);

ويمكن تمرير المُعاملات (لأسباب تاريخية أيضًا) في قائمة مفصولة بفواصل.

هذه التصريحات الثلاث لا تفرق عن بعضها البعض:

new Function('a', 'b', 'return a + b'); // الصياغة الأساس
new Function('a,b', 'return a + b'); // مفصولة بفواصل
new Function('a , b', 'return a + b'); // مفصولة بفواصل ومسافات

تُشير خاصية ‎[[Environment]]‎ للدوال ‎new Function‎ إلى البيئة المُعجمية العمومية لا الخارجية. بهذا لا يمكن لهذه الدوال استعمال المتغيرات الخارجية. إلّا أنّ ذلك أمر طيّب إذ تؤمّن لنا خطّ حماية لألا نصنع الأخطاء والمشاكل، فتمرير المُعاملات جهارةً أفضل بكثير من حيث بنية الشيفرة ولا تتسبّب مشاكل مع المُصغِّرات.

ترجمة -وبتصرف- للفصل The "new Function" syntax من كتاب 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.


×
×
  • أضف...