我目前正在编写一个JS规则引擎,它一度需要使用eval()函数来评估布尔表达式。
首先,我构建一个等式:
var equation = "relation.relatedTrigger.previousValue" + " " + relation.operator +
" " + "relation.value";
relation.relatedTrigger.previousValue 是我要比较的值。
relation.operator 是运营商(" ==","!=",< =,"< ",">",> =")。
relation.value 是我要与之比较的值。
然后我只是将这个字符串传递给eval函数,它返回true或false:
return eval(equation);
除了> =和< =之外,这非常合适(使用单词和数字)或所有运算符。例如。在评估等式时:
relation.relatedTrigger.previousValue <= 100
当previousValue = 0,1,10,100&amp;所有负数,但两者之间的所有内容都是假的。
我非常感谢任何人帮助回答我的问题或帮助我找到替代解决方案。
此致
奥吉尔。
P.S。我不需要就eval()函数的不安全性发表演讲。任何给予relation.relatedTrigger.previousValue的值都是预定义的。
编辑:这是完整的功能:
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);
}
}
答案:KennyTM在下面提供。字符串比较不起作用。需要转换为数字。
答案 0 :(得分:5)
您没有显示如何获得relation.relatedTrigger.previousValue
,但我猜这个变量的类型仍然是一个字符串。在这种情况下,右侧将被视为字符串。字符串比较符合您提到的所有特征:
>>> '-213' <= '100'
true
>>> '0' <= '100'
true
>>> '1' <= '100'
true
>>> '2' <= '100'
false
>>> '10' <= '100'
true
>>> '13' <= '100'
false
您需要确保relation.relatedTrigger.previousValue
是一个数字。一种解决方案是在比较中使用一元+运算符,例如
+relation.relatedTrigger.previousValue <= 100
这与eval
无关。问题是Javascript过于自由的隐式转换。
编辑:顺便说一句,您可以使用函数字典而不是eval。这更快,也更安全。请参阅http://jsperf.com/eval-vs-function-map。
var fmap = {
'>=': function(a, b) { return a >= b; },
...
};
fmap[relation.operator](+relation.relatedTrigger.previousValue,
+relation.value);
答案 1 :(得分:1)
比较字符串而不是数字。
确保relation.relatedTrigger.previousValue
和relation.value
是数字。
"11"
&gt; "100"
:因为11
按字母顺序排在100
之后。
11&lt; 100按数字顺序。
答案 2 :(得分:0)
var relation = {'relatedTrigger':{'previousValue':"7"}, 'operator':'<=', 'value': "100"};
var equation = "parseFloat(relation.relatedTrigger.previousValue)" + " " + relation.operator +
" " + "parseFloat(relation.value)";
alert(equation + ", " + eval(equation));
这实际上是你最终得到的结果,确保数值的额外步骤,而不是字符串传递似乎工作。