如何将对象作为作用域传递给eval?

时间:2019-01-25 19:08:57

标签: javascript

我有一个如下所示的javascript对象:

var myobj = {
    'a': 10, 'b': 20
}

我有一个条件存储在如下字符串中:

var c = 'a==10';

我想评估c中的条件是对还是错。条件字符串中引用的变量,例如amyobj的成员。

我尝试了以下操作,但没有帮助。

eval.call(myobj, 'a==10');

3 个答案:

答案 0 :(得分:4)

您应该真正质疑为什么要使用这样的动态JS内容。如果c的值是由用户提供的,那么您需要先清理该输入,然后才能在eval中使用它。几乎总是有更好的选择。

因此,我现在提出的解决方案实际上是在实施不良做法-在strict mode中不可用:

var res = eval('with (myobj) ' + c);

或者,根据您如何获取有关myobj的信息,这可能会更容易/更困难:

with (myobj) var res = eval(c);

所以现在让我们看一些更安全的方法。与其使用c这样的值,不如构建一个允许的表达式结构。例如:

var c = { prop: "a", operation: "equal", constant: 10 };

...然后执行以下操作:

var operations = {
    equal(a, b) => a == b,
    // define other operations here ...
};

function test(obj, c) {
    return operations[c.operation](obj[c.prop], c.constant);
}

答案 1 :(得分:0)

这是我尝试使用the Function constructor(用ES2015编写)针对此问题的超级解决方案:

const context = {
  a: 10,
  b: 20,
};

const expression = 'a==10';

const getAllMatches = (pattern, string) =>
      // make sure string is a String, and make sure pattern has the /g flag
      String(string).match(new RegExp(pattern, 'g'));

// this pattern is far from robust
const variablePattern = /[a-zA-Z$_][0-9a-zA-Z$_]*/;

const evalWithContext = (context, expression) => {
  const variables = getAllMatches(variablePattern, expression);

  // function and arguments are keywords, so I use abbreviated names
  const func = new Function(...variables, `return (${expression})`);

  const args = variables.map((arg) => (Object.hasOwnProperty.call(context, arg)
                                       ? context[arg]
                                       : undefined));

  return func(...args);
};

console.log(evalWithContext(context, expression));

答案 2 :(得分:-1)

太脏了:D

var myobj = {
    'a': 10,
    'b': 20
}

var c = 'a==10';

var res = (function() {
  return eval('this.' + c + ';');
}).apply(myobj);

console.log(res);

// or as onliner

var res2 = ((o) => eval('o.' + c)).call(null, myobj);
console.log(res2);