Вбудована функція eval
дозволяє виконувати рядок, як код.
Синтаксис:
let result = eval(code);
Наприклад:
let code = 'alert("Привіт")';
eval(code); // Привіт
Рядок коду може бути великий, містити перехід на інший рядок, оголошення функцій, змінні тощо.
Результатом eval
буде результат виконання останньої інструкції.
Наприклад:
let value = eval('1+1');
alert(value); // 2
let value = eval('let i = 0; ++i');
alert(value); // 1
Код eval
виконується в поточному лексичному середовищі, тому йому доступні зовнішні змінні:
let a = 1;
function f() {
let a = 2;
eval('alert(a)'); // 2
}
f();
Значення зовнішніх змінних можна змінювати:
let x = 5;
eval("x = 10");
alert(x); // 10, значення змінено
У строгому режимі у eval
є своє лексичне середовище. Тому функції та змінні, оголошені всередині eval
, не можна побачити ззовні:
// нагадування: режим 'use strict' включений за замовчуванням у всіх прикладах, що виконуються
eval("let x = 5; function f() {}");
alert(typeof x); // undefined (немає такої змінної)
// функція f теж недосяжна
Без use strict
у eval
не буде окремого лексичного середовища, тому x
та f
будуть видні із зовнішнього коду.
Використання “eval”
У сучасній розробці JavaScript eval
використовується дуже рідко. Є навіть відомий вираз – “eval is evil” (“eval – це зло”).
Причина такого ставлення досить проста: давно JavaScript був не дуже розвиненою мовою, і багато речей можна було зробити тільки за допомогою eval
. Але та епоха закінчилася понад десять років тому.
На цей час немає жодних причин, щоб продовжувати використовувати eval
. Якщо хтось все ще робить це, то дуже ймовірно, що вони легко зможуть замінити eval
більш сучасними конструкціями або JavaScript-модулями.
Будь ласка, майте на увазі, що код eval
здатний отримувати доступ до зовнішніх змінних, і це може мати побічні ефекти.
Мінімізатори коду (інструменти, що використовуються для стиснення JS-коду перед тим, як надіслати його кінцевим користувачам) замінюють локальні змінні на інші з короткими іменами для оптимізації. Зазвичай це безпечна маніпуляція, але не тоді, коли код використовується eval
, бо код з eval
може змінювати значення локальних змінних. Тому мінімізатори не чіпають імена змінних, які можуть бути доступні з eval
. Це погіршує рівень стиснення коду.
Використання всередині eval
локальних змінних із зовнішнього коду вважається поганим рішенням, оскільки це ускладнює завдання підтримки такого коду.
Існує два шляхи, як гарантовано уникнути таких проблем.
Якщо код всередині eval
не використовує зовнішніх змінних, то викликайте його так – window.eval(...)
:
У цьому випадку код виконується у глобальній області видимості:
let x = 1;
{
let x = 5;
window.eval('alert(x)'); // 1 (глобальна змінна)
}
Якщо коду всередині eval
потрібні локальні змінні, поміняйте eval
на new Function
та передавайте необхідні дані як аргументи:
let f = new Function('a', 'alert(a)');
f(5); // 5
Конструкція new Function
пояснюється у розділі Синтаксис "new Function". Вона створює функцію рядка в глобальній області видимості. Отже, локальні змінні для неї невидимі, але завжди можна передати їх як аргументи. Виходить дуже акуратний код, як у прикладі вище.
Підсумки
Виклик eval(code)
виконує рядок коду та повертає результат останньої інструкції.
- Це рідко використовується в сучасному JavaScript, тому що в цьому нема потреби.
- Можливий доступ до зовнішніх локальних змінних. Це вважається поганою практикою.
- Щоб виконати рядок коду за допомогою
eval
у глобальній області видимості, використовуйтеwindow.eval(code)
. - Або ж, якщо ваш код потребує якихось даних із зовнішньої області видимості, то використовуйте
new Function
, передавши ці дані як аргументи.
Коментарі
<code>
, для кількох рядків – обгорніть їх тегом<pre>
, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)