如果我有这个;
var a = "(true && false) && true && false"
如果我想评估这个字符串,有什么选择?
如果我说,这段代码将在浏览器中生成,但绝对没有用户输入,使用eval
是否安全?
如果没有,解析它的性能最高的是什么?
EDIt:
顺便说一句,字符串是动态的,所以我不能保证它总是像上面一样,所以它可能是:
var a = "(true && false) || (true && (true && false)) && true && false"
FIY: 我知道我可以使用eval,我要问的是,为什么我不应该使用eval,还是有其他选择?
编辑:原始问题: var a = function(){ return false} // all of them always return a boolean
var b = function(){ return true}
var c = function(){ return true}
var d = function(){ return false}
var conditions = "(a && b) && c && d"
我无法更改上面的代码,我需要解析它,我需要要评估的条件;
答案 0 :(得分:2)
function ExecuteJavascriptString() {
var n = 0;
var s = "(true || false) || (true || (true || false)) && true";
var ifstate = " if (" + s + ") { console.log('done'); } ";
setTimeout(ifstate, 1);
}
ExecuteJavascriptString()

答案 1 :(得分:0)
我想也许你可以使用RegExp eval
来验证字符串是否包含你认为它应该包含的内容,然后再运行/(?:(?:true)|(?:false)|(?:&&)|(?:\|\|)|[()\s])/g
:
var validExp = "(true && false && true) || (true && (true && false)) && true";
var evilExp = "(true && false && true) || (true && (true && false)) && true function() { console.log('do evil stuff'); }";
console.log(evalBoolStr(validExp)); //false
console.log(evalBoolStr(evilExp)); //Invalid input
function evalBoolStr(str) {
if(str.match(/(?:(?:true)|(?:false)|(?:&&)|(?:\|\|)|[()\s])/g).join('') === str) {
return eval(str);
}
return 'Invalid input';
}

答案 2 :(得分:0)
尝试为布尔字符串实际编写解析器:
function parseBoolStr(str) {
var expressions = {};
var expressionRegex = new RegExp("\\((?:(?:!*true)|(?:!*false)|(?:&&)|(?:\\|\\|)|\\s|(?:!*\\w+))+\\)");
var expressionIndex = 0;
str = str.trim();
while (str.match(expressionRegex)) {
var match = str.match(expressionRegex)[0];
var expression = 'boolExpr' + expressionIndex;
str = str.replace(match, expression);
match = match.replace('(', '').replace(')', '');
expressions[expression] = match;
expressionIndex++;
}
return evalBoolStr(str, expressions);
}
function evalBoolStr(str, expressions) {
var conditions = str.split(' ');
if (conditions.length > 0) {
var validity = toBoolean(conditions[0], expressions);
for (var i = 1; i + 1 < conditions.length; i += 2) {
var comparer = conditions[i];
var value = toBoolean(conditions[i + 1], expressions);
switch (comparer) {
case '&&':
validity = validity && value;
break;
case '||':
validity = validity || value;
break;
}
}
return validity;
}
return 'Invalid input';
}
function toBoolean(str, expressions) {
var inversed = 0;
while (str.indexOf('!') === 0) {
str = str.replace('!', '');
inversed++;
}
var validity;
if (str.indexOf('boolExpr') === 0) {
validity = evalBoolStr(expressions[str], expressions);
} else if (str == 'true' || str == 'false') {
validity = str == 'true';
} else {
validity = window[str]();
}
for (var i = 0; i < inversed; i++) {
validity = !validity;
}
return validity;
}
var exp1 = "(true && true || false) && (true || (false && true))";
var exp2 = "(true && false) && true && false";
var exp3 = "(true && !false) && true && !false";
var exp4 = "(a && b) && c && d";
console.log(exp1 + ' = ' + parseBoolStr(exp1));
console.log(exp2 + ' = ' + parseBoolStr(exp2));
console.log(exp3 + ' = ' + parseBoolStr(exp3));
console.log(exp4 + ' = ' + parseBoolStr(exp4));
function parseBoolStr(str) {
var expressions = {};
var expressionRegex = new RegExp("\\((?:(?:!*true)|(?:!*false)|(?:&&)|(?:\\|\\|)|\\s|(?:!*\\w+))+\\)");
var expressionIndex = 0;
str = str.trim();
while (str.match(expressionRegex)) {
var match = str.match(expressionRegex)[0];
var expression = 'boolExpr' + expressionIndex;
str = str.replace(match, expression);
match = match.replace('(', '').replace(')', '');
expressions[expression] = match;
expressionIndex++;
}
return evalBoolStr(str, expressions);
}
function evalBoolStr(str, expressions) {
var conditions = str.split(' ');
if (conditions.length > 0) {
var validity = toBoolean(conditions[0], expressions);
for (var i = 1; i + 1 < conditions.length; i += 2) {
var comparer = conditions[i];
var value = toBoolean(conditions[i + 1], expressions);
switch (comparer) {
case '&&':
validity = validity && value;
break;
case '||':
validity = validity || value;
break;
}
}
return validity;
}
return 'Invalid input';
}
function toBoolean(str, expressions) {
var inversed = 0;
while (str.indexOf('!') === 0) {
str = str.replace('!', '');
inversed++;
}
var validity;
if (str.indexOf('boolExpr') === 0) {
validity = evalBoolStr(expressions[str], expressions);
} else if (str == 'true' || str == 'false') {
validity = str == 'true';
} else {
validity = window[str]();
}
for (var i = 0; i < inversed; i++) {
validity = !validity;
}
return validity;
}
function a() {
return false;
}
function b() {
return true;
}
function c() {
return true;
}
function d() {
return false;
}
&#13;
然后用法只是parseBoolStr('true && false'); //false