eval
在JavaScript中是邪恶的! MDN评估页面指出:
过时的
此功能已过时。 尽管浏览器仍支持它,但在新项目中不鼓励使用它。 尽量避免使用它。
eval
执行包含代码的字符串,例如
eval("var x = 'Hello from eval!';");
console.log(x);
eval
提出了几个问题:
- 安全性:您的字符串可以通过第三方脚本或用户输入与其他命令一起注入。
- 调试:调试错误很困难-您没有行号或明显的故障点。
- 优化:JavaScript解释器不一定会预先编译代码,因为它可能会更改。 尽管解释器已经变得越来越高效,但几乎可以肯定它会比本地代码运行得慢。
不幸的是, eval
非常强大,对于经验不足的开发人员来说,容易过度使用该命令。
尽管有警告,但eval
仍然有效(即使在严格模式下也是如此),但是您通常可以避免这种情况。 过去,它主要用于反序列化JSON字符串,但现在有了更安全的JSON.parse
方法。
但是,如果我们在字符串中有一个函数名,例如
// function we want to run
var fnstring = "runMe";
function runMe() {
// do stuff
}
我们如何在不使用eval
情况下执行runMe()
函数? 我最近在使用HTML5历史记录API时遇到了这种情况; pushState方法不允许您存储对函数的直接引用,因此您需要将其名称定义为字符串。 使用Web Workers或对象序列化的任何其他API,您也可能面临类似的挑战。
最简单,最安全的无评估执行解决方案是一系列条件,例如
// function we want to run
var fnstring = "runMe";
switch (fnstring) {
case "functionX": functionX(); break;
case "functionY": functionY(); break;
case "functionZ": functionZ(); break;
case "runMe": runMe(); break;
}
这是安全的,但是如果您有数十种可能的函数调用,则编写起来效率低下且痛苦。
更好的解决方案是使用引用当前窗口及其中所有项目的window
对象。 我们可以检查fnstring
是否可以作为window
的对象使用,如果它是一个函数,可以运行它,例如
// function we want to run
var fnstring = "runMe";
// find object
var fn = window[fnstring];
// is object a function?
if (typeof fn === "function") fn();
您可以根据需要执行其他检查,以确保该功能具有期望的名称。
如果我们要调用的函数具有参数(可能存储在数组中)怎么办? 没问题; 我们只使用apply
方法:
// function name and parameters to pass
var fnstring = "runMe";
var fnparams = [1, 2, 3];
// find object
var fn = window[fnstring];
// is object a function?
if (typeof fn === "function") fn.apply(null, fnparams);
因此,这是停止使用eval
的另一个原因。 另外,此解决方案更安全,更不易出错,更易于调试,并且通常可以更快地执行。 希望对您有所帮助。
From: https://www.sitepoint.com/call-javascript-function-string-without-using-eval/