٢٠ مارس ٢٠٢١

الدالّة "Eval" لتنفيذ الشيفرة البرمجية

تنفذ الدالّة Eval المضمّنة في اللغة الشيفرات البرمجية المُمرّرة لها كسلسلة نصية string.

وصياغتها هكذا:

let result = eval(code);

فمثلًا:

let code = 'alert("Hello")';
eval(code); // Hello

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

ولكن نتيجة الدالّة Eval هي نتيجة آخر عبارة منفذة في الشيفرة.

وإليك المثال التالي:

let value = eval('1+1');
alert(value); // 2
let value = eval('let i = 0; ++i');
alert(value); // 1

تُنفذّ الشيفرة في البيئة الحالية للدالّة، ولذا فيمكنها رؤية المتغيرات الخارجية:

let a = 1;

function f() {
  let a = 2;

  eval('alert(a)'); // 2
}

f();

كما يمكنها تعديل المتغيّرات الخارجية أيضًا:

let x = 5;
eval("x = 10");
alert(x); // النتيجة: ‫10، تعدلت القيمة بنجاح

في الوضع الصارم، تملك الدالّة Eval بيئة متغيّرات خاصة بها. لذا فلن تظهر الدوالّ والمتغيرات، المعرفة -داخل الدالة- للخارج وإنما ستبقى بداخلها:

// تذكر أن في الوضع الصارم يُشغّلُ تلقائيًا في الأمثلة الحيّة
eval("let x = 5; function f() {}");

alert(typeof x); // undefined (المتحول غير مرئي هنا)
// ‫الدالّة f غير مرئية هنا أيضًا

بدون تفعيل “الوضع صارم”، لن يكون للدالّة Eval بيئة متغيرات خاصة بها، ولذلك سنرى المتغيّر x والدالّة f من خارج الدالّة.

استخدامات الدالّة “Eval”

في طرق البرمجة الحديثة، نادرًا ما تستخدم الدالّة Eval. وغالبًا ما يقال عنها أنها أصل الشرور.

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

حاليًا، لا يوجد سبب وجيه لاستخدامها. ولو أن شخصًا يستخدمها الآن فلديه الإمكانية لاستبدالها بالبنية الحديثة للغة أو بالوحدات.

لاحظ أن إمكانية وصول الدالة eval للمتغيرات الخارجية لها عواقب سيئة.

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

يُعدّ استخدام المتغيّرات المحلية في الشيفرة بداخل الدالّة Eval من الممارسات البرمجية السيئة، لأنه يزيد صعوبة صيانة الشيفرة.

هناك طريقتان لضمان الأمان الكامل عند مصادفتك مثل هذه المشاكل.

إذا لم تستخدم الشيفرة الممررة للدالّة المتغيرات الخارجية، فمن الأفضل استدعاء الدالّة هكذا: window.eval(...)‎

بهذه الطريقة ستُنفذّ الشيفرة في النطاق العام:

let x = 1;
{
  let x = 5;
  window.eval('alert(x)'); // 1 (global variable)
}

إن احتاجت الشيفرة الممررة للدالة Eval لمتغيّرات خارجية، فغيّر Eval لتصبح new Function ومرّر المتغير كوسيط. هكذا:

let f = new Function('a', 'alert(a)');

f(5); // 5

شرحنا في مقالٍ سابق تعلمنا كيفية استخدام صياغة «الدالة الجديدة» new Function. إذ باستخدام هذه الصياغة ستُنشأ دالة جديدة من السلسلة (String)، في النطاق العام. لذا لن تتمكن من رؤية المتغيرات المحلية. ولكن من الواضح أن تمريرها المتغيرات صراحة كوسطاء سيحلّ المشكلة، كما رأينا في المثال أعلاه.

خلاصة

سيُشغّل استدعاء الدالّة eval(code)‎ الشيفرة البرمجية المُمرّرة ويعيد نتيجة العبارة الأخيرة.

  • نادرًا ما تستخدم هذه الدالّة في الإصدارات الحديثة للغة، إذ لا توجد حاجة ماسّة لها.
  • يمكننا الوصول دائمًا للمتغيّرات الخارجية في الدالّة eval. ولكن يعدّ ذلك من الممارسات السيئة.
  • بدلًا من ذلك يمكننا استخدام الدالة eval في النطاق العام، هكذا window.eval(code)‎.
  • أو، إذا كانت الشيفرة الخاصة بك تحتاج لبعض البيانات من النطاق الخارجي، فاستخدم صياغة الدالّة الجديدة ومرّر لها المتغيرات كوسطاء.

التمارين

آلة حاسبة باستخدام الدالة Eval

الأهمية: 4

أنشئ آلة حاسبة تطالب بتعبير رياضي وتُعيد نتيجته.

لا داعي للتحقق من صحة التعبير في هذا التمرين. فقط قيّم التعبير وأعد نتيجته.

لرؤية المثال الحي

الحل

لنستخدم الدالة eval لحساب التعبير الرياضي:

let expr = prompt("Type an arithmetic expression?", '2*3+2');

alert( eval(expr) );

يستطيع المستخدم أيضًا إدخال أي نص أو شيفرة.

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

ترجمة -وبتصرف- للفصل Eval: run a code string من كتاب The JavaScript language

مهمه

الأهمية: 4

Create a calculator that prompts for an arithmetic expression and returns its result.

There’s no need to check the expression for correctness in this task. Just evaluate and return the result.

قم بتشغيل العرض التوضيحي

Let’s use eval to calculate the maths expression:

let expr = prompt("Type an arithmetic expression?", '2*3+2');

alert( eval(expr) );

The user can input any text or code though.

To make things safe, and limit it to arithmetics only, we can check the expr using a regular expression, so that it only may contain digits and operators.

خريطة الدورة التعليمية