Is there a way to calculate a formula stored in a string in JavaScript without using eval()?
Normally I would do something like
var apa = "12/5*9+9.4*2";
console.log(eval(apa));So, does anyone know about alternatives to eval()?
You could use the Function() constructor, which is similar to eval (never run it on untrusted input):
function evil(fn) {
  return new Function('return ' + fn)();
}
console.log(evil('12/5*9+9.4*2')); // => 40.4Eval was built for conditions like this.
If you wanted another method, you'd have to use a pure Javascript implementation of the exact thing eval is going to do.
Here's a quick basic example I came up with (updated (2011-06-26): cleaner w/ input boxes).
http://jsfiddle.net/vol7ron/6cdfA/  
Note:
Edit (2017-05-26) to use SO Snippet:
function calculate(input) {
  var f = {
    add: '+',
    sub: '-',
    div: '/',
    mlt: '*',
    mod: '%',
    exp: '^'
  };
  // Create array for Order of Operation and precedence
  f.ooo = [
    [
      [f.mlt],
      [f.div],
      [f.mod],
      [f.exp]
    ],
    [
      [f.add],
      [f.sub]
    ]
  ];
  input = input.replace(/[^0-9%^*\/()\-+.]/g, ''); // clean up unnecessary characters
  var output;
  for (var i = 0, n = f.ooo.length; i < n; i++) {
    // Regular Expression to look for operators between floating numbers or integers
    var re = new RegExp('(\\d+\\.?\\d*)([\\' + f.ooo[i].join('\\') + '])(\\d+\\.?\\d*)');
    re.lastIndex = 0; // take precautions and reset re starting pos
    // Loop while there is still calculation for level of precedence
    while (re.test(input)) {
      output = _calculate(RegExp.$1, RegExp.$2, RegExp.$3);
      if (isNaN(output) || !isFinite(output)) 
        return output; // exit early if not a number
      input = input.replace(re, output);
    }
  }
  return output;
  function _calculate(a, op, b) {
    a = a * 1;
    b = b * 1;
    switch (op) {
      case f.add:
        return a + b;
        break;
      case f.sub:
        return a - b;
        break;
      case f.div:
        return a / b;
        break;
      case f.mlt:
        return a * b;
        break;
      case f.mod:
        return a % b;
        break;
      case f.exp:
        return Math.pow(a, b);
        break;
      default:
        null;
    }
  }
}label {
  display: inline-block;
  width: 4em;
}<div>
  <label for="input">Equation: </label>
  <input type="text" id="input" value="12/5*9+9.4*2-1" />
  <input type="button" 
         value="calculate" 
         onclick="getElementById('result').value = calculate(getElementById('input').value)" />
</div>
<div>
  <label for="result">Result: </label>
  <input type="text" id="result" />
</div>(/[^0-9%^*\/()\-+.]/g, '');: ^ does not need to be escaped?Here is an implementation of the Shunting-yard algorithm with additional support for unary prefix (e.g. -) and postfix (e.g. !) operators, and function (e.g. sqrt()) notations. More operators/functions can be easily defined with the Calculation.defineOperator method:
"use strict";
class Calculation {
    constructor() {
        this._symbols = {};
        this.defineOperator("!", this.factorial,      "postfix", 6);
        this.defineOperator("^", Math.pow,            "infix",   5, true);
        this.defineOperator("*", this.multiplication, "infix",   4);
        this.defineOperator("/", this.division,       "infix",   4);
        this.defineOperator("+", this.last,           "prefix",  3);
        this.defineOperator("-", this.negation,       "prefix",  3);
        this.defineOperator("+", this.addition,       "infix",   2);
        this.defineOperator("-", this.subtraction,    "infix",   2);
        this.defineOperator(",", Array.of,            "infix",   1);
        this.defineOperator("(", this.last,           "prefix");
        this.defineOperator(")", null,                "postfix");
        this.defineOperator("min", Math.min);
        this.defineOperator("sqrt", Math.sqrt);
        this.defineOperator("pi", Math.PI); // A constant
    }
    // Method allowing to extend an instance with more operators and functions:
    defineOperator(symbol, f, notation = "func", precedence = 0, rightToLeft = false) {
        // Store operators keyed by their symbol/name. Some symbols may represent
        // different usages: e.g. "-" can be unary or binary, so they are also
        // keyed by their notation (prefix, infix, postfix, func):
        if (notation === "func") precedence = 0;
        this._symbols[symbol] = Object.assign({}, this._symbols[symbol], {
            [notation]: {
                symbol, f, notation, precedence, rightToLeft, 
                argCount: 1 + (notation === "infix")
            },
            symbol,
            regSymbol: symbol.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&')
                + (/\w$/.test(symbol) ? "\\b" : "") // add a break if it's a name 
        });
    }
    last(...a)           { return a[a.length-1] }
    negation(a)          { return -a }
    addition(a, b)       { return a + b }
    subtraction(a, b)    { return a - b }
    multiplication(a, b) { return a * b }
    division(a, b)       { return a / b }
    factorial(a) {
        if (a%1 || !(+a>=0)) return NaN
        if (a > 170) return Infinity;
        let b = 1;
        while (a > 1) b *= a--;
        return b;
    }
    calculate(expression) {
        let match;
        const values = [],
            operators = [this._symbols["("].prefix],
            exec = _ => {
                let op = operators.pop();
                values.push(op.f(...[].concat(...values.splice(-op.argCount))));
                return op.precedence;
            },
            error = msg => {
                let notation = match ? match.index : expression.length;
                return `${msg} at ${notation}:\n${expression}\n${' '.repeat(notation)}^`;
            },
            pattern = new RegExp(
                // Pattern for numbers
                "\\d+(?:\\.\\d+)?|" 
                // ...and patterns for individual operators/function names
                + Object.values(this._symbols)
                        // longer symbols should be listed first
                        .sort( (a, b) => b.symbol.length - a.symbol.length ) 
                        .map( val => val.regSymbol ).join('|')
                + "|(\\S)", "g"
            );
        let afterValue = false;
        pattern.lastIndex = 0; // Reset regular expression object
        do {
            match = pattern.exec(expression);
            let [token, bad] = match || [")", undefined];
            // Replace constant names (like PI) with corresponding value
            if (typeof this._symbols[token]?.func?.f === "number") token = this._symbols[token].func?.f;
            const notNumber = this._symbols[token],
                notNewValue = notNumber && !notNumber.prefix && !notNumber.func,
                notAfterValue = !notNumber || !notNumber.postfix && !notNumber.infix;
            // Check for syntax errors:
            if (bad || (afterValue ? notAfterValue : notNewValue)) return error("Syntax error");
            if (afterValue) {
                // We either have an infix or postfix operator (they should be mutually exclusive)
                const curr = notNumber.postfix || notNumber.infix;
                do {
                    const prev = operators[operators.length-1];
                    if (((curr.precedence - prev.precedence) || prev.rightToLeft) > 0) break; 
                    // Apply previous operator, since it has precedence over current one
                } while (exec()); // Exit loop after executing an opening parenthesis or function
                afterValue = curr.notation === "postfix";
                if (curr.symbol !== ")") {
                    operators.push(curr);
                    // Postfix always has precedence over any operator that follows after it
                    if (afterValue) exec();
                }
            } else if (notNumber) { // prefix operator or function
                operators.push(notNumber.prefix || notNumber.func);
                if (notNumber.func) { // Require an opening parenthesis
                    match = pattern.exec(expression);
                    if (!match || match[0] !== "(") return error("Function needs parentheses")
                }
            } else { // number
                values.push(+token);
                afterValue = true;
            }
        } while (match && operators.length);
        return operators.length ? error("Missing closing parenthesis")
                : match ? error("Too many closing parentheses")
                : values.pop() // All done!
    }
}
Calculation = new Calculation(); // Create a singleton
// I/O handling
function perform() {
    const expr = document.getElementById('expr').value,
        result = Calculation.calculate(expr);
    document.getElementById('out').textContent = isNaN(result) ? result : '=' + result;
}
document.getElementById('expr').addEventListener('input', perform);
perform();
// Tests
const tests = [
    { expr: '1+2', expected: 3 },
    { expr: '1+2*3', expected: 7 },
    { expr: '1+2*3^2', expected: 19 },
    { expr: '1+2*2^3^2', expected: 1025 },
    { expr: '-3!', expected: -6 },
    { expr: '12---11+1-3', expected: -1 },
    { expr: 'min(2,1,3)', expected: 1 },
    { expr: '(2,1,3)', expected: 3 },
    { expr: '4-min(sqrt(2+2*7),9,5)', expected: 0 },
    { expr: '2,3,10', expected: 10 },
    { expr: 'pi*2', expected: Math.PI*2 },
]
for (let {expr, expected} of tests) {
    let result = Calculation.calculate(expr);
    console.assert(result === expected, `${expr} should be ${expected}, but gives ${result}`);
}#expr { width: 100%; font-family: monospace }Expression: <input id="expr" value="min(-1,0)+((sqrt(16)+(-4+7)!*---4)/2)^2^3"><p>
<pre id="out"></pre>* as the default operation? Ex: (1)1 throws error while it should be treated as (1)*1.This is exactly the place where you should be using eval(), or you will have to loop through the string and generate the numbers. You will have to use the Number.isNaN() method to do it.
If you don't want to use eval you will have to use an existing expression evaluator library.
http://silentmatt.com/javascript-expression-evaluator/
http://www.codeproject.com/KB/scripting/jsexpressioneval.aspx
You can also roll one of your own :)
eval() with one step removed.I spent a couple of hours to implement all the arithmetical rules without using eval() and finally I published a package on npm string-math. Everything is in the description. Enjoy
This solution also clips whitespaces and checks for duplicating operators
e.g. ' 1+   2 *2' // 5 but ' 1  +   +2* 2 ' // Error
function calcMe(str) {
  const noWsStr = str.replace(/\s/g, '');
  const operators = noWsStr.replace(/[\d.,]/g, '').split('');
  const operands = noWsStr.replace(/[+/%*-]/g, ' ')
                          .replace(/\,/g, '.')
                          .split(' ')
                          .map(parseFloat)
                          .filter(it => it);
  if (operators.length >= operands.length){
    throw new Error('Operators qty must be lesser than operands qty')
  };
  while (operators.includes('*')) {
    let opIndex = operators.indexOf('*');
    operands.splice(opIndex, 2, operands[opIndex] * operands[opIndex + 1]);
    operators.splice(opIndex, 1);
  };
  while (operators.includes('/')) {
    let opIndex = operators.indexOf('/');
    operands.splice(opIndex, 2, operands[opIndex] / operands[opIndex + 1]);
    operators.splice(opIndex, 1);
  };
  while (operators.includes('%')) {
    let opIndex = operators.indexOf('%');
    operands.splice(opIndex, 2, operands[opIndex] % operands[opIndex + 1]);
    operators.splice(opIndex, 1);
  };
  let result = operands[0];
  for (let i = 0; i < operators.length; i++) {
    operators[i] === '+' ? (result += operands[i + 1]) : (result -= operands[i + 1])
  }
  return result
}
This shows to be more performant than @vol7ron's solution.
Check this JSBenchmark 
If you're looking for a syntactical equivalent to eval, you could use new Function.  There are slight differences regarding scoping, but they mostly behave the same, including exposure to much of the same security risks:
let str = "12/5*9+9.4*2"
let res1 = eval(str)
console.log('res1:', res1)
let res2 = (new Function('return '+str)())
console.log('res2:', res2)You can't, at most you could do something retort like parsing the numbers and then separating the operations with a switch, and making them. Other than that, I'd use eval in this case.
That would be something like (a real implementation will be somewhat more complex, especially if you consider the use of parenthesis, but you get the idea)
function operate(text) {
  var values = text.split("+");
  return parseInt(values[0]) + parseInt(values[1]);
}
console.log(operate("9+2"));Still, I think the best choice you can make is to use eval, given that you're able to trust the source of the string.
There is also an open source implementation on GitHub, evaluator.js, and an NPM package.
From the README: Evaluator.js is a small, zero-dependency module for evaluating mathematical expressions.
All major operations, constants, and methods are supported. Additionally, Evaluator.js intelligently reports invalid syntax, such as a misused operator, missing operand, or mismatched parentheses.
Evaluator.js is used by a desktop calculator application of the same name. See a live demo on the website.
Note : There is no library used in this solution purely hard coded
My solution takes into account of brackets also like 8+6(7(-1)) or 8+6(7(-1))
You can do these operations ^, *, /, +, -
To calculate a string use calculate(tokenize(pieval("8+6(7(-1))").join("")))
function tokenize(s) {
    // --- Parse a calculation string into an array of numbers and operators
    const r = [];
    let token = '';
    for (const character of s) {
        if ('^*/+-'.indexOf(character) > -1) {
            if (token === '' && character === '-') {
                token = '-';
            } else {
                r.push(parseFloat(token), character);
                token = '';
            }
        } else {
            token += character;
        }
    }
    if (token !== '') {
        r.push(parseFloat(token));
    }
    return r;
}
function calculate(tokens) {
    // --- Perform a calculation expressed as an array of operators and numbers
    const operatorPrecedence = [{'^': (a, b) => Math.pow(a, b)},
               {'*': (a, b) => a * b, '/': (a, b) => a / b},
               {'+': (a, b) => a + b, '-': (a, b) => a - b}];
    let operator;
    for (const operators of operatorPrecedence) {
        const newTokens = [];
        for (const token of tokens) {
            if (token in operators) {
                operator = operators[token];
            } else if (operator) {
                newTokens[newTokens.length - 1] = 
                    operator(newTokens[newTokens.length - 1], token);
                operator = null;
            } else {
                newTokens.push(token);
            }
        }
        tokens = newTokens;
    }
    if (tokens.length > 1) {
        console.log('Error: unable to resolve calculation');
        return tokens;
    } else {
        return tokens[0];
    }
}
function pieval(input) {
  let openParenCount = 0;
  let myOpenParenIndex = 0;
  let myEndParenIndex = 0;
  const result = [];
  for (let i = 0; i < input.length; i++) {
    if (input[i] === "(") {
      if (openParenCount === 0) {
        myOpenParenIndex = i;
        // checking if anything exists before this set of parentheses
        if (i !== myEndParenIndex) {
            if(!isNaN(input[i-1])){
                result.push(input.substring(myEndParenIndex, i) + "*");
            }else{
                result.push(input.substring(myEndParenIndex, i));
            }
        }
      }
      openParenCount++;
    }
    if (input[i] === ")") {
      openParenCount--;
      if (openParenCount === 0) {
        myEndParenIndex = i + 1;
        // recurse the contents of the parentheses to search for nested ones
        result.push(pieval(input.substring(myOpenParenIndex + 1, i)));
      }
    }
  }
  // capture anything after the last parentheses
  if (input.length > myEndParenIndex) {
    result.push(input.substring(myEndParenIndex, input.length));
  }
  //console.log(cal(result))
  let response = cal(result);
  return result;
}
function cal(arr) {
  let calstr = "";
  for (let i = 0; i < arr.length; i++) {
    if (typeof arr[i] != "string") {
      if (cal(arr[i]) < 0) {
        arr[i] = `${cal(arr[i])}`;
      } else {
        arr[i] = `${cal(arr[i])}`;
      }
    }
    if (typeof arr[i] === "string") {
      calstr += arr[i];
    }
    if (i == arr.length - 1) {
      //console.log("cal" ,calstr,calculate(tokenize(calstr)) );
      return calculate(tokenize(calstr));
    }
  }
}
console.log(calculate(tokenize(pieval("8+6(7(-1))").join("")))); // ["1+",["2-",["3+4"]]]
console.log(calculate(tokenize(pieval("1+(1+(2(4/4))+4)").join("")))); // ["1+",["2-",["3+4"]]]
evalas long as you can be sure about what the string you are evaluating contains.evalin a web app is not a security risk. If someone wants to inject code into your web app, they can just open it up in the chrome debugger and modify the code! The only time you need to worry about security is if you are using eval() on the server, such as node.js