Sterling Archer
Sterling Archer

Reputation: 22425

Simplified Dynamic Arithmetic Operator

I'm revisiting this old project I tackled a while back where I wanted to avoid using if statements and switch blocks to render say a simple calculation where the operator ( + / - / / / * ) could be anything.

I am retrieving data from a database (securely inserted), along with a beta case of user input (again, painstakingly secured with validation) via ajax. That works fine, yay, great. Now we come to the demon I've heard so much about. eval().

If you take the time to read up, modern browsers using something like the V8 engine can cache the compiled eval. People say it creates vulnerability via injection. If you offer efficient validation and avoid any critical application mis-structures, how can it be harmful?

//note I'm using var just for clarity, this is NOT the declaration or assignment statment
//also note the variables are stored in an array because the condition can be dynamic in size, but that's overhead for now

var firstNum = 50;
var secondNum = 100;
var operator = "+";
var condition = firstNum+operator+secondNum;

if (eval(condition) > 149) { //not the real condition, just an example
    console.log("Success");
}

Is this still not safe? Is it more efficient than a switch statement? Nested if statements? If performance isn't an issue and you do know what you're doing, can eval() be good, and not.. wait for it.. evil()?

Note: Yes I have seen the other questions about eval() yet I still haven't found a reason for this to even exist because people treat it like a leper.

This basically comes down to: what is the best way to handle a condition where the mathematical operator is not a static value?

Upvotes: 2

Views: 1887

Answers (1)

cHao
cHao

Reputation: 86565

eval is harmful partly because

  • you have to be rather careful in order to avoid code injection.
  • most IDEs can't catch stupid syntax errors in a dynamically built string.
  • it has historically sucked performancewise.
  • it's basically using a sledgehammer to swat a fly, which is the big cause of a lot of the other reasons. Very, very few situations benefit from that much flexibility, and most just get worse.

In this case, you could do something like

var operators = {
    '+' : function(a, b) { return a + b; },
    '-' : function(a, b) { return a - b; },
    '*' : function(a, b) { return a * b; },
    '/' : function(a, b) { return a / b; },
};

var firstNum = 50;
var secondNum = 100;
var op = operators['+'];

if (op(firstNum, secondNum) > 149) {
    console.log('Success');
}

and end up with all the dynamism you're looking for with your eval, with none of the downsides. You get to define exactly what operations you want to allow, and what's more, you're not even limited to infix operators -- you could have a 'max' operator, or a 'round', for example.

Upvotes: 11

Related Questions