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

新手上路,请多包涵

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

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

javascript 中是否有一种直接的方法来解析它们,以便它们像一组条件一样工作。就像是:

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

原文由 Ashish Ranjan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

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

1.使用模板文字:

它们在实际使用中受到限制,因为它们与使用它们的脚本一起被解析,但 它们也是安全的

 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
};

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

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

这个 规则 结构可以很容易地保存和加载为 JSON 字符串。

原文由 trincot 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

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

这是一个例子:

 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 ,因为它无法访问您使用它的范围内的所有内容,但它们都是强大的工具你需要警惕。

原文由 T.J. Crowder 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题