Выполнение математических операций: альтернативы eval в JavaScript
Доброго времени суток! Представим, что у нас есть некоторое математическое выражение, полученной от пользователя и которое необходимо выполнить. Например вычислить результат математической операции в JavaScript калькуляторе. Первое, что приходит на ум — это использование выражения eval в JavaScript
Использование eval() для оценки выражений в калькуляторе может быть рискованным, так как выражение может выполнить произвольный код и создать уязвимости, особенно если используется ввод от пользователя. Более безопасный подход — вручную разбирать и оценивать математические выражения.
Вот несколько безопасных альтернатив eval() для создания калькулятора:
1. Использование математической библиотеки JavaScript
Вы можете использовать библиотеки, такие как math.js, которые безопасно выполняют математические выражения без риска выполнения произвольного кода.
Пример с использованием Math.js:
Сначала установите библиотеку:
npm install mathjs
Затем, в вашем JavaScript-коде:
// Импортируйте библиотеку math.js
const math = require('mathjs');
function calculate(expression) {
try {
return math.evaluate(expression); // Безопасная оценка математического выражения
} catch (error) {
return "Недопустимое выражение!";
}
}
console.log(calculate("2 + 3 * (7 - 4)")); // Выводит 11
2. Ручной разбор
Если вы хотите избежать использования внешних библиотек, вы можете создать простой калькулятор, разбирая ввод самостоятельно, поддерживая только базовые арифметические операции, такие как сложение, вычитание, умножение и деление.
Пример простого калькулятора без eval():
function calculate(expression) {
try {
// Разделите выражение на числа и операторы
let operators = expression.replace(/[0-9]|./g, "").split("");
let numbers = expression.split(/[^0-9.]+/).map(Number);
let result = numbers[0];
for (let i = 0; i < operators.length; i++) {
switch (operators[i]) {
case '+':
result += numbers[i + 1];
break;
case '-':
result -= numbers[i + 1];
break;
case '*':
result *= numbers[i + 1];
break;
case '/':
result /= numbers[i + 1];
break;
default:
return "Недопустимая операция!";
}
}
return result;
} catch (error) {
return "Недопустимое выражение!";
}
}
console.log(calculate("2+3*4")); // Выводит 14
3. Использование конструктора Function
Несколько менее безопасной альтернативой eval() является использование конструктора Function. Этот метод требует осторожности, но считается безопаснее, чем прямое использование eval().
function calculate(expression) {
try {
const func = new Function("return " + expression);
return func();
} catch (error) {
return "Недопустимое выражение!";
}
}
console.log(calculate("2 + 3 * (7 - 4)")); // Выводит 11
4. Регулярные выражения для валидации
Вы можете использовать регулярные выражения, чтобы убедиться, что ввод содержит только разрешенные символы (такие как цифры и операторы). Этот метод напрямую не оценивает выражение, но обеспечивает проверку ввода.
Пример с проверкой через регулярное выражение:
function calculate(expression) {
const validExpression = /^[0-9+-*/().s]+$/;
if (!validExpression.test(expression)) {
return "Недопустимое выражение!";
}
try {
return new Function("return " + expression)();
} catch (error) {
return "Недопустимое выражение!";
}
}
console.log(calculate("2 + 3 * (7 - 4)")); // Выводит 11
console.log(calculate("2 + alert('Hacked!')")); // Возвращает "Недопустимое выражение!"