如何在不使用eval的情况下从字符串调用JavaScript函数

eval在JavaScript中是邪恶的! MDN评估页面指出:

过时的
此功能已过时。 尽管浏览器仍支持它,但在新项目中不鼓励使用它。 尽量避免使用它。

eval执行包含代码的字符串,例如

eval("var x = 'Hello from eval!';");
console.log(x);

eval提出了几个问题:

  1. 安全性:您的字符串可以通过第三方脚本或用户输入与其他命令一起注入。
  2. 调试:调试错误很困难-您没有行号或明显的故障点。
  3. 优化: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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值