Чому eval небезпечний?
Функція eval() - одна з найбільш "небезпечних" і суперечливих функцій у JavaScript.
Розберемо детально, що вона робить, чому її часто уникають, і чим можна замінити.
Що робить eval()
eval() виконує рядок коду JavaScript як програму.
eval("console.log('Привіт із eval!')");Вивід:
Привіт із eval!По суті, eval() бере рядок і змушує рушій JavaScript виконати його як звичайний JS-код.
Приклади використання eval()
Приклад 1: виконання виразу
const x = 10;
const y = 5;
console.log(eval("x + y")); // 15eval "розуміє", що рядок "x + y" - це вираз, і повертає результат.
Приклад 2: створення змінних (небезпечно)
eval("var z = 100;");
console.log(z); // 100Проблема: змінна z створюється в поточній області видимості,
і може перезаписати наявні значення.
Приклад 3: динамічний код (погана практика)
function runCode(code) {
eval(code);
}
runCode("alert('Виконуємо довільний код')");Це виконає будь-який код, який передали рядком. Якщо цей код прийшов від користувача: можна отримати XSS-атаку або повне захоплення застосунку.
Чому не рекомендується використовувати eval()
Ось основні причини:
1. Небезпека для безпеки (XSS, ін'єкції)
const userInput = "alert('Злам!')";
eval(userInput); // виконається прямо в браузері!Це прямий шлях до XSS-атак і витоку даних.
2. Зниження продуктивності
Код у eval() виконується повільніше,
тому що JS-рушій не може оптимізувати його (він не знає, що там, заздалегідь).
Кожен виклик eval() змушує рушій заново аналізувати й інтерпретувати рядок коду.
3. Ламає область видимості
Код всередині eval() може створювати або змінювати змінні поточного контексту,
що робить код непередбачуваним і важким для налагодження.
let a = 10;
eval("a = 99;");
console.log(a); // 99, значення змінилося "зсередини"4. Погано читається і важко підтримується
eval() робить код магічним і непередбачуваним:
незрозуміло, що саме буде виконано, поки не буде передано рядок.
Безпечні альтернативи eval()
| Завдання | Чим замінити |
|---|---|
| Виконати математичний вираз | Function() або готовий парсер (наприклад, math.js) |
| Перетворити JSON | JSON.parse() |
| Виконати динамічний код із заздалегідь відомих функцій | Об'єкт з мапінгом функцій |
| Отримати властивість за іменем | obj[propName], а не eval("obj." + propName) |
Приклади заміни
Погано:
eval("user.name = 'Oleh'");Добре:
user["name"] = "Oleh";Погано:
const obj = eval("(" + jsonStr + ")");Добре:
const obj = JSON.parse(jsonStr);Погано:
eval("sum(5, 10)");Добре:
const actions = { sum: (a, b) => a + b };
actions["sum"](5, 10);Коротко запам'ятати
| Що робить | Виконує рядок як JS-код |
|---|---|
| Безпека | Дуже небезпечно: XSS та ін'єкції |
| Продуктивність | Повільно |
| Налагодження | Складно |
| Оптимізація | Блокує JIT |
| Використовувати | Тільки у вкрай рідкісних випадках, коли точно контролюєш рядок |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.