javascript - Finns det kända problem med >= och <= och eval-funktionen i JS?
Jag skriver för närvarande en JS-regelmotor som vid ett tillfälle behöver utvärdera booleska uttryck med funktionen eval().
För det första konstruerar jag en ekvation på följande sätt:
var equation = "relation.relatedTrigger.previousValue" + " " + relation.operator +
" " + "relation.value";
relation.relatedTrigger.previousValue är värdet jag vill jämföra.
relation.operator är operatorn (antingen "==", "!=", <=, "<", ">", >=).
relation.value är värdet jag vill jämföra med.
Jag skickar sedan helt enkelt den här strängen till eval-funktionen och den returnerar true eller false på följande sätt:
return eval(equation);
Detta fungerar alldeles utmärkt (med ord och siffror) eller alla operatörer förutom >= och <=. T.ex. när man utvärderar ekvationen:
relation.relatedTrigger.previousValue <= 100
Det returnerar sant när previousValue=0,1,10,100 och alla negativa tal men falskt för allt däremellan.
Jag skulle verkligen uppskatta hjälp från vem som helst att antingen svara på min fråga eller hjälpa mig att hitta en alternativ lösning.
Vänliga hälsningar,
Augier.
P.S. Jag behöver inget tal om osäkerheterna hos eval()-funktionen. Alla värden som ges till relation.relatedTrigger.previousValue är fördefinierade.
redigera: Här är hela funktionen:
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);
}
}
Svar: Tillhandahålls av KennyTM nedan. En strängjämförelse fungerar inte. Det var nödvändigt att konvertera till ett numeriskt värde.
Svar #1
Du visade inte hur relation.relatedTrigger.previousValue erhålls, men jag antar att typen av denna variabel fortfarande är en sträng. I så fall kommer höger sida istället att behandlas som en sträng. En strängjämförelse matchar alla egenskaper du nämnde:
>>> '-213' <= '100'
true
>>> '0' <= '100'
true
>>> '1' <= '100'
true
>>> '2' <= '100'
false
>>> '10' <= '100'
true
>>> '13' <= '100'
false
Du behöver se till att relation.relatedTrigger.previousValue är ett nummer. En lösning är att använda den unära +-operatorn i jämförelsen, till exempel.
+relation.relatedTrigger.previousValue <= 100
Detta har ingenting att göra med eval. Problemet är den alltför liberala implicita konverteringen i Javascript.
Redigera: Förresten, istället för eval kan du använda en ordlista med funktioner istället. Detta är snabbare och också säkrare. Se http://jsperf.com/eval-vs-function-map.
var fmap = {
'>=': function(a, b) { return a >= b; },
...
};
fmap[relation.operator](+relation.relatedTrigger.previousValue,
+relation.value);
Svar #2
Det jämför strängar, inte siffror.
Se till att relation.relatedTrigger.previousValue och relation.value är siffror.
"11" > "100": Eftersom 11 kommer efter 100 i alfabetisk ordning.
11 < 100 i numerisk ordning.
