我需要计算用户输入的算术表达式,比如Javascript中的"2 * (3 + 4)“,但出于安全原因,我不想使用eval。
我可以剔除除数字或运算符以外的所有字符,但我不确定这样做是否安全,如果用户可以使用cos、sqrt等函数就更好了。
有没有可以做算术表达式求值的Javascript库?
发布于 2011-02-21 22:18:48
你可以试试JavaScript Expression Evaluator
这个库是拉斐尔·格拉夫的ActionScript表达式解析器的修改版本。当我编写JavaScript函数绘图器时,我想要一个比使用JavaScript函数更好的。目前没有安全风险,因为您只能在自己的浏览器中运行代码,但是对于数学运算(Math.pow(2^x)而不是2^x,依此类推)就不那么方便了。
那么你的代码将会是这样的:
console.info ( Parser.evaluate( "2 * (3 + 4)" ) ); //prints 14发布于 2011-02-21 22:38:50
正如已经提到的,任何用户可能造成的最大破坏几乎是他们在任何主要浏览器中使用内置控制台所能做的事情。但是,如果您希望限制用户使用Math属性/方法,则可以编写一个简单的正则表达式来为您处理此问题。像这样的东西应该是有效的:
function mathEval (exp) {
var reg = /(?:[a-z$_][a-z0-9$_]*)|(?:[;={}\[\]"'!&<>^\\?:])/ig,
valid = true;
// Detect valid JS identifier names and replace them
exp = exp.replace(reg, function ($0) {
// If the name is a direct member of Math, allow
if (Math.hasOwnProperty($0))
return "Math."+$0;
// Otherwise the expression is invalid
else
valid = false;
});
// Don't eval if our replace function flagged as invalid
if (!valid)
alert("Invalid arithmetic expression");
else
try { alert(eval(exp)); } catch (e) { alert("Invalid arithmetic expression"); };
}我知道您出于安全原因不想使用eval,但是正则表达式应该使它非常安全,因为它排除了任何不是Math对象的直接属性的单词和大多数非数学JS操作符,包括赋值操作符(=)和二元操作符。更难的方法是编写一个记号赋予器来解析数学表达式,因为它不是一种常规语言。
请随时尝试打破我写的working example,如果你可以,或者如果你注意到一个问题,请留下评论,我会看看我能做些什么来修复它。
注:奕江提到了in JavaScript chat,对于像Math.PI这样的东西,允许小写可能也是有用的。如果是这种情况,您只需在替换函数中添加以下else if语句:
else if (Math.hasOwnProperty($0.toUpperCase())
return "Math."+$0.toUpperCase();将其添加到if和else语句(example)之间。
发布于 2013-04-28 20:38:29
您可以使用math.js的高级表达式解析器,它不使用JavaScript。
http://mathjs.org
用法:
var ans = math.evaluate('2 * (3 + 4)');或者使用解析器(它支持变量和函数赋值):
var parser = math.parser();
var ans = parser.evaluate('2 * (3 + 4)');https://stackoverflow.com/questions/5066824
复制相似问题