将字符串解析为javaScript中的条件?

时间:2017-04-04 09:23:11

标签: javascript parsing

我有一个包含一些条件的字符串,例如:

var str = "this.demoModel.active == '1' && this.demoModel.span > 5 || ..."

是否有一种直接的方式在javascript中解析它们,以便它们像一组条件一样工作。类似的东西:

if (JSON.parse(str) {})。 ??

5 个答案:

答案 0 :(得分:7)

有,但使用它们通常是最后的手段:evalFunction构造函数。 eval在调用eval的上下文中从字符串输入运行代码。 Function构造函数从字符串创建函数。当然,在这两种情况下,这意味着您必须信任字符串的来源,因为它可以包含任意代码,并且您很乐意在代码的上下文中运行它。例如,你不会从用户A拿一个字符串,然后在用户B的浏览器中运行它 - 这将使用户B对用户A的攻击敞开大门。(对于“浏览器”替代“会话”或其他什么,问题就像在Node这样的环境中一样真实 - 或许更多 - 服务器端,因为它在brwoser中是客户端的。)

如果你接受用户的字符串并在他们自己的浏览器/会话/上下文中运行它,那很好。

以下是一个例子:

function Foo() {
  this.demoModel = {
    active: "1",
    span: 7
  };
}
Foo.prototype.run = function(str) {
  if (eval(str)) {
    console.log("Yes");
  } else {
    console.log("No");
  }
};
var f = new Foo();
f.run("this.demoModel.active == '1' && this.demoModel.span > 5");
f.run("this.demoModel.active == '0' && this.demoModel.span < 5");

您还可以使用Function构造函数,然后使用正确的this调用它:

function Foo() {
  this.demoModel = {
    active: "1",
    span: 7
  };
}
Foo.prototype.run = function(str) {
  var testfunc = new Function("return " + str);
  if (testfunc.call(this)) {
    console.log("Yes");
  } else {
    console.log("No");
  }
};
var f = new Foo();
f.run("this.demoModel.active == '1' && this.demoModel.span > 5");
f.run("this.demoModel.active == '0' && this.demoModel.span < 5");

如果您 执行此操作,请尽可能选择Function构造函数到eval,因为它无法访问您使用它的范围内的所有内容,但它们都是你需要警惕的强大工具。

答案 1 :(得分:5)

您可以使用&#39; eval&#39;或者&#39;功能&#39;但正如所述on MDN

  

不要不必要地使用eval! -   eval()是一个危险的函数,它执行它以调用者的特权传递的代码。如果您使用可能受恶意方影响的字符串运行eval(),您最终可能会使用您的网页/扩展程序的权限在用户的计算机上运行恶意代码。更重要的是,第三方代码可以看到调用eval()的范围,这可能会导致类似函数不易受影响的攻击。<​​/ p>

if(new Function("CONDITON_STRING")()){
 //Answer
};

答案 2 :(得分:5)

一般情况下,您应该尽量避免陷入这种情况:如果可能的话,应该避免将JavaScript存储在字符串中以供以后评估。根据您的实际情况,您可以考虑以下选项:

1。使用模板文字:

它们在实际使用中受到限制,因为它们与使用它们的脚本一起解析,但是they are also safe

var str =  `${this.demoModel.active == '1' && this.demoModel.span > 5}`;

分配此字符串后,它会立即评估其中的${ }部分。

因此,如果评估可以立即进行,这只是一种解决方案,因为您无法将其存储在字符串中,然后期望稍后触发评估。

因此与以下内容没有太大区别:

var bool = this.demoModel.active == '1' && this.demoModel.span > 5;

2。通过回调延迟评估

解决方法可能是定义一个评估模板文字或表达式的函数,如下所示:

var rule = function() { 
    return this.demoModel.active == '1' && this.demoModel.span > 5;
};

...你可以传递该函数,例如作为回调:

doSomething(rule);

...然后 doSomething 可以这样调用它,绑定上下文,以便this具有适当的值:

function doSomething(rule) {
    if (rule.call(this)) console.log('rule passed');
}

3。嵌套对象数据结构

另一个选择是为表达式创建一个对象结构,例如:

var rules = [
    [{ // AND conditions:
        "field": "active",
        "compare": "eq",
        "target": 1
    }, {
        "field": "span",
        "compare": "gt",
        "target": 5
    }], // Next array will be OR'ed
    [{
        "field": "...."
        "compare": "..",
        "target": ...
    }]
}];

这是一个嵌套数组,其中顶级将具有必须一起“或”的规则,而内部级别将被“和”在一起。

然后编写一个处理此结构的函数。 比较名称可以映射到代码中的函数,如下所示:

const comparators = {
    "eq": (a, b) = a === b,
    "gt": (a, b) = a > b
};

因此,要评估 rules 数组中的一个对象,可以使用:

execute: (obj) => comparators[this.demoModel[obj.compare]] // get the function
    (this.demoModel[obj.field], obj.target) // pass arguments

规则结构可以轻松保存并作为JSON字符串加载。

答案 3 :(得分:2)

尝试以下方法:

var str =  'true && true';
var str2 =  'true && false';
function strEval(fn) {
  return new Function('return ' + fn)();
}
var conditionTrue = strEval(str);
var conditionFalse = strEval(str2)
if(conditionTrue)
{
    console.log(conditionTrue)
}
if(!conditionFalse)
{
    console.log(conditionFalse)
}

答案 4 :(得分:-1)

使用eval方法将字符串转换为命令。

var cond = 'd === 1';
var d = 0;

if (eval(cond)) { console.log('1'); } else { console.log('2'); }    // output: 2
d = 1;
if (eval(cond)) { console.log('1'); } else { console.log('2'); }    // output: 1