推荐在JavaScript中执行存储为字符串的函数,而不是使用eval

Recommended way to Execute a function stored as String in JavaScript instead of using eval

本文关键字:函数 eval 字符串 JavaScript 执行 存储      更新时间:2023-09-26

在有人将其标记为重复之前,这篇文章实际上并没有回答这个问题,而是提出了一种完全不同的方法来解决这个特定的问题。

我的是另一个问题。请让我解释一下。

在我的例子中,有各种.js文件(插件),它们与jquery getscript一起加载并存储在变量中然后,无论何时需要,都将执行(不止一次)

加载脚本的代码(此代码在每个插件js文件的系统初始化时只运行一次)

var storedFunc;
$.getScript(pathToPluginJSFile, function( data, textStatus, jqxhr ) {
    storedFunc = data;    
});

所有插件都是这种格式

(function(){
  //lots of code here
})()

但当我在控制台中检查storedFunc变量时,我发现它被存储为String变量。像这样,

"(function(){
      //lots of code here
 })()"

现在为了执行这个,我使用了eval,就像这样(这个代码可以根据需要执行多次)

eval(storedFunc)

一切都很好,我对此很满意,但问题来了,我在某个地方读到使用eval有点不好。所以现在我担心,如果认为一切都很正常,那么在互联网上使用eval传播的所有负面信息可能会吓跑我的客户。:(

所以,请告诉我如何在不使用eval的情况下运行存储函数(它已经变成了一个字符串)。

或者,我应该使用$.getScript以外的任何不将函数转换为字符串的东西吗?

或者,是否有其他方法可以完全重写这个插件功能?

请给我指路。我急需这个解决方案。

任何帮助都将不胜感激。

提前谢谢。

了解$.getScript如何工作

$.getScript的工作原理似乎有些混乱。如果您注意到jQuery关于该方法的文档,并且正如@Pointy在评论中提到的那样,这是:

使用GET HTTP请求从服务器加载JavaScript文件,然后执行

这里有一个例子:让我们假设返回的文件的内容只有这个:

// Contents of yourExternalFile.js
console.log('Executed!');

现在,当您使用$.getScript:时

$.getScript(pathToPluginJSFile, function( data, textStatus, jqxhr ) {
    // The script you retrieved has already executed at this point, and you will find "Executed!" in the console.
    console.log('All Done');
});

控制台输出:

> Executed!
> All Done

$.getScript方法不用于返回文件内容的字符串。然而,尽管回调中有可用的数据,但文件的内容已经执行。因此,通过获取文件的字符串版本,并使用new Function甚至eval重新执行它,您就可以在页面上执行它两次(jQuery执行一次,您也执行一次)。


原始帖子:

请使用Function构造函数而不是eval

// Your function as a string stored to a variable
var stringFunction = "(function(){console.log('Executed');})()";
// Use the Function constructor to create a new function:
var executableFunction = new Function(stringFunction);
// Now you can execute it
executableFunction(); // logs "Executed"

这个SO问题/答案中的这个片段解决了evalnew Function之间的差异。

  • eval()将字符串计算为当前执行范围内的JavaScript表达式,并可以访问局部变量。

  • new Function()将存储在字符串中的JavaScript代码解析为一个函数对象,然后可以调用该函数对象。它无法访问局部变量,因为代码在单独的作用域中运行。


附加信息(基于评论)

是的,您可以只获取文件的字符串内容,并将它们存储到一个变量中,而不执行文件的内容。您可以随时执行该函数。您只需要使用jquery使用常规的get方法,并将dataType设置为text。这样,脚本就不会执行,您可以按照自己的意愿执行:

var storedFunction;
$.get({url: pathToPluginJSFile, dataType: 'text'})
    .done(function (data) {
        // Turn the script into a new function and store it
        // The information in the script file has not done anything yet
        storedFunction = new Function(data);
    })
    .fail(function () {
        console.log('Failed :(');
    });

您唯一需要注意的是,在进行api调用时,确保将函数分配给storedFunction变量,并且必须等待调用完成后再尝试执行该函数。

// Later on, call that function anytime, and as often as you want:
storedFunction();