۷ فوریه ۲۰۲۰

Eval: یک رشته را به عنوان کد اجرا کنید

تابع درونی eval اجازه می دهد تا یک رشته از کد را اجرا کنید

دستور:

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

رشته در محیط جاری اجرا می شود بنابراین به متغییر های خارجی در Scope دسترسی دارد:

let a = 1;

function f() {
  let a = 2;

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

f();

همچنین می تواند متغییر های خارجی را نیز تغییر دهد:

let x = 5;
eval("x = 10");
alert(x); // 10, value modified

در strict mode, eval محیط خاص خودش را دارد. بنابراین توابع و متغییر های اعلان شده در eval در خارج قابل دسترسی نیستند:

// reminder: 'use strict' is enabled in runnable examples by default

eval("let x = 5; function f() {}");

alert(typeof x); // undefined (no such variable)
// function f is also not visible

بدون use strict, eval محیط خاص خودش را ندارد, بر این اساس ما x و f در خارج قابل دسترسی اند.

استفاده از “eval”

در برنامه نویسی مدرن eval به ندرت استفاده میشود. به طور معمول گفته می شود “eval is evil”.

دلیلش ساده است: خیلی وقت پیش جاوااسکریپت یک زبان بسیار ضعیف تر بود، خیلی چیز ها تنها می توانستند با eval انجام شوند اما یک دهه از آنگاه می گذرد.

اکنون, هیچ دلیلی برای استفاده از eval نیست. اگر کسی از آن استفاده می کند، میتواند برای جایگزین کردن آن از ساخت های مدرن زبان یا JavaScript Module بهره بگیرد.

لطفا توجه کنید که قابلیت آن برای دسترسی به متغییر های خارجی عوارض جانبی دارد.

) فشرده کنندگان کدCode minifiers( متغیر های محلی را به نام های کوتاه تر تغییر نام می دهند (مانند aو b) برای کوتاه کردن کد. این کار معمولا مشکلی ایجاد نمی کند اما نه وقتی که eval استفاده شده, از آنجا که متغییر های محلی شاید از طریق eval مورد استفاده قرار گرفته باشند بنابراین خرد کنندگان متغییر هایی که می توانند توسط eval مورد استفاده قرا گرفته باشند را تغییر نمی دهند که باعث کاهش ضریب فشرده سازی می شود.

استفاده از متغییر های درون eval در خارج از آن همچنین نامناسب است, چراکه نگهداری کد را سخت تر می کند.

دو را برای ایمن ماندن از چنین مشکلاتی وجود دارد.

اگر eval از متغییر های خارجی استفاده نمی کند, لطفا eval را به صورت window.eval(...) فرا بخوانید:

در این صورت رشته در محیط عمومی (global scope) اجرا می شود

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

اگر رشته کد نیاز به متغییر های خارجی دارد, eval را به new Function تغییر دهید و آنها را به عنوان آرگومان به آن پاس دهید:

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

f(5); // 5

new Function در بخش توضیح داده شده است سینتکس "new Function". آن یک تابع با استفاده از یک رشته ایجاد می کند, همچنین در محیط عمومی. بنابراین آن نمی تواند دیگر متغییر های محلی را ببیند اما آن بسیار بهتر است که آنها صریحا به عنوان آرگومان پاس دهیم، مانند مثال بالا.

جمع بندی

فراخوانی eval(code) رشته کد را اجرا می کند و نتیجه آخرین عملیات را بر می گرداند.

  • به ندرت در جاوااسکریپت مدرن مورد استفاده است, چراکه معمولا نیازی به آن نیست.
  • می تواند به متغییر های محلی خارجی دسترسی یابد. که نامناسب در نظر گرفته شده.
  • به جای eval کد را در محیط عمومی اجرا کنید و از window.eval(code) استفاده کنید.
  • یا اگر کد شما داده هایی از محیط خارجی نیاز دارد از new Function استفاده کنید و به عنوان آرگومان ها به آن پاس دهید.

تمارین

اهمیت: 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.

نقشه آموزش