Are s> = and <= issues known and the eval function in JS?

I'm currently writing a JS rule engine, which at some point should evaluate Boolean expressions using the eval () function.

First I will build the equation as such:

 var equation = "relation.relatedTrigger.previousValue" + " " + relation.operator + " " + "relation.value"; 

the relation .relatedTrigger.previousValue is the value I want to compare.

relation.operator is an operator (either "==", "! =", <=, "<", ">",> = ").

the .value relation is the value I want to compare with.

Then I just pass this line to the eval function and return true or false as such:

 return eval(equation); 

This works absolutely fine (with words and numbers) or all operators except> = and <=. For instance. When evaluating the equation:

 relation.relatedTrigger.previousValue <= 100 

Returns true when previousValue = 0,1,10,100 and all negative numbers, but false for everything in between.

I would greatly appreciate the help of anyone who could answer my question or help me find an alternative solution.

Hi,

Ogier.

PS I do not need to talk about the uncertainty of the eval () function. Any value assigned to .relatedTrigger.previousValue is predefined.

edit: Here is the full function:

 function evaluateRelation(relation) { console.log("Evaluating relation") var currentValue; //if multiple values if(relation.value.indexOf(";") != -1) { var values = relation.value.split(";"); for (x in values) { var equation = "relation.relatedTrigger.previousValue" + " " + relation.operator + " " + "values[x]"; currentValue = eval(equation); if (currentValue) return true; } return false; } //if single value else { //Evaluate the relation and get boolean var equation = "relation.relatedTrigger.previousValue" + " " + relation.operator + " " + "relation.value"; console.log("relation.relatedTrigger.previousValue " + relation.relatedTrigger.previousValue); console.log(equation); return eval(equation); } } 

Answer: Provided by KennyTM below. String comparison does not work. A conversion to a number is required.

+6
source share
3 answers

You have not shown how relation.relatedTrigger.previousValue obtained, but I think the type of this variable is still a string. In this case, the right side will be considered as a string. String comparison matches all your specifications:

 >>> '-213' <= '100' true >>> '0' <= '100' true >>> '1' <= '100' true >>> '2' <= '100' false >>> '10' <= '100' true >>> '13' <= '100' false 

You need to make sure relation.relatedTrigger.previousValue is a number. One solution uses the unary + operator in comparison, for example

 +relation.relatedTrigger.previousValue <= 100 

This has nothing to do with eval . The problem is overly liberal implicit conversion in Javascript.


Edit: By the way, instead of eval, you can use a function dictionary. It is faster and safer. See http://jsperf.com/eval-vs-function-map .

 var fmap = { '>=': function(a, b) { return a >= b; }, ... }; fmap[relation.operator](+relation.relatedTrigger.previousValue, +relation.value); 
+5
source

This is a comparison of strings, not numbers.

Make sure relation.relatedTrigger.previousValue and relation.value are numbers.

"11" > "100" : Because 11 comes after 100 in alphabetical order.

11 <100 in numerical order.

+1
source
 var relation = {'relatedTrigger':{'previousValue':"7"}, 'operator':'<=', 'value': "100"}; var equation = "parseFloat(relation.relatedTrigger.previousValue)" + " " + relation.operator + " " + "parseFloat(relation.value)"; alert(equation + ", " + eval(equation)); 

This is effective in what you end up with, and the extra step of providing a numerical value, rather than the lines passed in, seems to work.

0
source

Source: https://habr.com/ru/post/925913/


All Articles