Javascript 调用绕过eval()的函数

Javascript 调用绕过eval()的函数,javascript,eval,Javascript,Eval,我正在使用一个使用eval函数的Javascript代码 eval(myString) myString=myFunc(arg)的值,我想不使用eval直接调用myFunc 我无法控制要调用的函数,因为我将该函数作为字符串(这里是myString)获取。 该函数的参数也是同一字符串的一部分 那么,有没有什么方法可以在不使用eval的情况下调用预期的函数呢?除了使用eval之外,JavaScript不提供任何方法来调用表示为字符串的函数。不过,使用它并没有什么错。鉴于您没有其他选择。您可能会尝试

我正在使用一个使用eval函数的Javascript代码

eval(myString)
myString=myFunc(arg)的值,我想不使用eval直接调用myFunc

我无法控制要调用的函数,因为我将该函数作为字符串(这里是myString)获取。 该函数的参数也是同一字符串的一部分


那么,有没有什么方法可以在不使用eval的情况下调用预期的函数呢?

除了使用eval之外,JavaScript不提供任何方法来调用表示为字符串的函数。不过,使用它并没有什么错。鉴于您没有其他选择。

您可能会尝试使用
功能

var sure = function(s) {
  return confirm(s);
};
var str = 'sure("Are you sure?")';
var rtn = new Function('return ' + str)();
alert(rtn);

我有点怀疑是否允许用户提供函数名,但是。。。假设变量中有函数名,变量中有arg值。吊杆:

var myString = window[fn](arg);
arg
可能已经在一个参数中,所以这很简单。下一部分是分析函数名。只要一点正则表达式:

var fn = /^([a-z0-9_]+)\(arg\)$/i.exec(str)[1];
if (fn && typeof window[fn] === 'function') {
  window[fn](arg);
}
当然,这确实假设函数总是在全局范围内,但如果不是,您应该能够相应地进行调整。而且,我的正则表达式只是我想到的第一件事。它可能没有涵盖所有可能的函数名

如果您想将字符串限制为一组特定的函数(您几乎可以肯定应该这样做),那么一旦您有了函数名,这也变得非常容易:

var allowedFunctions = {fn1: fn1, fn2: fn2, someOtherFunction: function() {} },
    fn = /^([a-z0-9_]+)\(arg\)$/i.exec(str)[1];

if (fn && allowedFunctions[fn]) {
    allowedFunctions[fn](arg);
} else {
    // Hah, nice try.
}

(如果
arg
实际上不是一个变量名,而是某种文字或任意表达式,这会变得更复杂,也更不安全。)

为什么不使用eval?将字符串评估为Javascript是eval的具体用途。我认为没有其他方法,但我无法控制输入字符串。因此字符串的提供者可以发送一个恶意字符串,eval将执行该字符串,因此我想删除eval函数。我认为您可能需要在这里为我们提供更多的上下文。您担心
eval
的安全风险,但您正试图运行从其他地方提供的代码-这就是风险所在,不在您使用的特定机制中。如果你接受并执行任意代码,你就是在冒险,句号。“不过,使用它并没有错,因为你没有其他选择。”---我会记住这个理由。似乎对每种情况都是通用的。我得到了:意外的字符串文字“return”应为参数列表中的参数或“')。似乎如果代码通过上述RegExp,那么使用eval()获取函数本身不会有风险,并且可能达到window.fnName无法达到的非全局闭包。简而言之,在这种情况下,eval()只能指向一个预先存在的函数,它不会执行任意代码。@dandavis确实如此。我想,一旦验证了格式,
eval
就相对安全了。不过,基于对象的白名单函数比基于正则表达式的白名单函数更容易,而且据我所知,只要eval是
f(a)
,就可用范围而言,它相当于以编程方式调用
window[fn](a)
。如果它是直接eval(),则它可以访问周围函数的范围,比如AMD加载程序的非窗口回调参数。如果你使用间接评估,那么是的,它只是全局评估