调用函数在所选对象上保存为字符串

时间:2018-04-19 13:18:56

标签: javascript function call

我有类似的东西:

var sFunction = 'my_function("param1", "param2")';
var oMyObject = ...;

我希望将它结合起来,结果将等于:

oMyObject.my_function("param1", "param2");

非常感谢任何提示。

备注

正如你们许多人建议找到根本原因并尽量不处理有问题的输入,这里有一些关于"问题的起源的信息"。
sFunction来自数据库,在其中一列中进行了硬编码。它是自定义的,应根据sFunction的数据库记录的其他参数检索对象。
因此,在您的评论支持下,我将尝试建议更改数据模型,希望对此并不太晚。感谢大家的帮助。

3 个答案:

答案 0 :(得分:1)

  

我被认为是输入,它可能来自db或其他任何地方。我只需要用描述的方式处理它。

作为Luca noted,你可能最好解决这个问题,这个问题会让你在字符串中找到你认为需要在运行时评估的代码。这样做的用例数非常少。

例如,而不是

sFunction = 'my_function("param1", "param2")';

也许你可以拥有

call = {
    f: "my_function",
    params: ["param1", "param2"]
};

然后是:

oMyObject[call.f].apply(oMyObject, call.params);

call甚至可以作为你解析的JSON文本开始生活 - 实例:

var json =
  '{' +
      '"f": "my_function",' +
      '"params": ["param1", "param2"]' +
  '}';
var call = JSON.parse(json);
var oMyObject = {
    my_function: function(p1, p2) {
        console.log(p1, p2);
    }
};

oMyObject[call.f].apply(oMyObject, call.params);

显然比任意代码执行更安全。

可以使用sFunctioneval("oMyObject." + sFunction))执行此操作,但请考虑:

  • 它允许sFunction中的任意代码运行。

  • 如果用户A提供代码,然后在用户B的系统上运行,则会损害用户B的隐私。 (我不是律师,但您可能会以违反国家/地区数据保护或隐私法的方式这样做。)

现在,如果您从数据库加载代码,并且您知道数据库中的代码只能由受信任的人(例如,您团队中的开发人员,最终用户)放在那里系统),没关系,它很像运行脚本文件。但是几乎可以肯定有一种更好的方法,而不是将代码作为字符串传递并eval

但如果代码来自“其他任何地方”,则罚款;见上面的要点。从根本上打破了设置,提供了更好的选择。把这些信息传递给你的老板,如果有必要的话,给他/她的老板,如果有必要,他/她的老板,直到你找到一个可以改变要求的人。

答案 1 :(得分:0)

这是一个不使用eval()的字符串黑客,但正如我(和其他人)所说,这不是一个好的解决方案。更好的解决方案是将函数名称和任何参数作为逗号分隔的字符串返回,这至少可以使这种解决方案更直接。

var sFunction = 'my_function("param1", "param2")';

// The object would have to already have the function:
var oMyObject = {
  my_function: function(x,y){
    return x + y;
  }
};

// Remove the last ")" and split the remainder into an array at the "("
var funcParts = sFunction.replace(")","").split("(");

// Split the second part (the arguments) into its own array
var funcArgs = funcParts[1].split(",");

// Pass the function name as a string key to the object and then pass the arguments to that
console.log(oMyObject[funcParts[0]](funcArgs[0], funcArgs[1]));

更大的问题是,你最终想要完成什么,因为几乎总有比这更好的方法。

答案 2 :(得分:0)

要进行动态函数调用,您当然可以像我在评论中那样进行评估,这当然是一个糟糕的主意。这是一个快速而又肮脏的选择:

const dynamicCallMethod = (obj, s) => {
  try {
    const fname = s.match(/([$\w]+\(/);
    const params = s.match(/("[\w$]+")/g);
    return obj[fname](...params);
  } catch (e) {
    return e;
  }
};

注意如果您更详细地描述方案,我仍然认为有更简单的方法可以做到这一点。例如,上述任何非ascii字符都将失败。