تابع درونی 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
استفاده کنید و به عنوان آرگومان ها به آن پاس دهید.