eval()的最佳替代方法是将字符串转换回函数?

时间:2016-08-26 07:16:27

标签: jquery

由于我已经听到很多人使用eval()和新功能()因为它的超动态性而被认为是不安全的功能。 我只需要将一个最初是函数的字符串转换回函数,以便在其他集群中使用此函数。 这是一个简单的测试程序,我为了您的方便而开发,它用于eval()函数,并且它工作正常。除了eval()甚至是新的Function()??

之外还有其他方法吗?
$(document).ready(function(){

savecallback = function() {
alert("testing savecallback");
}

var stringname = "function() {alert("testing savecallback");}";

jQuery(".divclass").click(function() {
 eval(stringname);
});

});

编辑:

对不起伙计们,实际上字符串存储整个函数实现而不是函数名称,用于我在项目文件中检查过的内容。编辑了上面的代码(在var stringname中)。

3 个答案:

答案 0 :(得分:0)

eval()和new Funciton()不安全的原因正是因为它们可以生成和/或运行可执行代码。您确实需要生成可执行代码,因此您将找到任何不安全的方法。

答案 1 :(得分:0)

我猜你可能会有更好的全面解决方案 - 你想要解决的问题的更多信息可能会有所帮助:)

根据您发布的内容,我会考虑为您的函数使用对象属性,然后保存对象属性名称而不是完整的函数执行字符串:

// object to store callbacks on
var callbacks = {};

// define your callback
callbacks['savecallback'] = function() {
  alert('testing savecallback');
}

// save your callback name
var stringname = 'savecallback';

jQuery(".divclass").click(function() {
  // call your callback by name
  callbacks[stringname]();
});

如果有部分或全部代码无法控制(回调定义或保存的字符串),请告诉我们 - 有办法解决这个问题。如果在窗口范围内定义了回调,则可以window[stringname]();,如果无法更改回调字符串,则可以stringname = stringname.replace('()','');。在任何情况下,如果您可以使用字符串来识别要运行的函数而不是实际eval,那么这将是最好的。

编辑:如果整个函数实现都是字符串,那么你几乎会遇到eval。您可以尝试将字符串插入到脚本标记内的dom中,但这会像eval一样危险,如果它甚至可以工作(未经测试)。几乎每当你想要执行的代码都是字符串格式时,你就冒着在该字符串中执行任何旧内容的风险。只要你意识到风险,eval就不是世界末日 - 尽量保持封闭,例如:

function getEvalClosure(evalCode) {
  return function() { return eval(evalCode); }
}

jQuery(".divclass").click(function() {
  var f = (getEvalClosure(stringname))();
  // i noticed your code is itself a function, 
  // so you'd have to run it after eval-ing it into existence
  f();
});

它永远不会'安全',但请记住最终用户无论如何都可以使用你的javascript的任何部分,因此我不建议首先在客户端javascript中做任何过于敏感的事情。在这种情况下,'getEvalClosure'函数为eval创建一个新的作用域,使其与其余代码保持一致。在每个库自动执行之前,我曾经非常广泛地使用eval来转换来自AJAX请求的字符串化JSON - 实际上我打赌即使在那些实现中仍然存在eval()或两个。

祝你好运!

答案 2 :(得分:0)

如果您有一个固定的功能列表要调用(即您事先知道所有可能的功能),您可以创建一个string->函数的映射,并根据字符串键查找该函数。

这样,您可以安全地调用这些函数,而不必担心在用户的输入上运行危险的eval()

例如:

$(document).ready(function(){

    savecallback = function() {
        alert("testing savecallback");
    }

    anothercallback = function() {
        alert("testing anothercallback");
    }

    var availableFunctions = {
        "savecallback()": savecallback,
        "anothercallback()": anothercallback
    };

    var stringname = "savecallback()";

    jQuery(".divclass").click(function() {
        if (stringname in availableFunctions) {
            availableFunctions[stringname].call();
        }
    });

});